The props
value in useState(props)
is used only during the initial render, further state updates are done with the setter setNameState
.
In addition, there is no need for useEffect
when updating derived state:
const Person = props => {
const [nameState, setNameState] = useState(props.name);
if (props.name !== nameState) setNameState(props.name);
};
From React docs:
[...] you can update the state right during rendering. React will re-run the component with updated state immediately after exiting the first render so it wouldn’t be expensive.
[...] an update during rendering is exactly what getDerivedStateFromProps
has always been like conceptually.
In essence, we can optimize performance by getting rid of an additional browser repaint phase, as useEffect
always runs after the render is committed to the screen.
Working example
This is a contrived example illustrating above pattern - in real code you would read props.name
directly. See the React blog post for more appropriate derived state use cases.
const Person = props => {
const [nameState, setNameState] = React.useState(props.name);
if (props.name !== nameState) setNameState(props.name);
return (
<p>
<h3>Person</h3>
<div>{nameState} (from derived state)</div>
<div>{props.name} (from props)</div>
<p>Note: Derived state is synchronized/contains same value as props.name</p>
</p>
);
};
const App = () => {
const [personName, setPersonName] = React.useState("Lui");
const changeName = () => setPersonName(personName === "Lukas" ? "Lui" : "Lukas");
return (
<div>
<Person name={personName} />
<button onClick={changeName}>Change props</button>
</div>
);
};
ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.13.0/umd/react.production.min.js" integrity="sha256-32Gmw5rBDXyMjg/73FgpukoTZdMrxuYW7tj8adbN8z4=" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.13.0/umd/react-dom.production.min.js" integrity="sha256-bjQ42ac3EN0GqK40pC9gGi/YixvKyZ24qMP/9HiGW7w=" crossorigin="anonymous"></script>
<div id="root"></div>
setNameState
. – ManavMuseEffect
– ManavM