I know how to use prevState in new State, I want to know how does it actually works ?? How does this functionality works ?? why on putting in 'prevValue' in 'setFullName' function changes its value ?
import React, { useState } from "react";
function App() {
const [fullName, setFullName] = useState({
firstName: "",
lastName: ""
});
function handleChange(event) {
let value = event.target.value;
let name = event.target.name;
setFullName((prevValue) => {
if (name === "fName") {
return {
firstName: value,
lastName: prevValue.lastName
};
} else if (name === "lName") {
return {
firstName: prevValue.firstName,
lastName: value
};
}
});
}
return (
<div className="container">
<h1>
{fullName.firstName} {fullName.lastName}
</h1>
<form>
<input onChange={handleChange} name="fName" placeholder="First Name" />
<input onChange={handleChange} name="lName" placeholder="Last Name" />
<button>Submit</button>
</form>
</div>
);
}
export default App;
CodePudding user response:
When a component is created (with React.createElement
, or with JSX like <App />
), React will see how many times useState
is called in the component body, and will create an internal mapping of state indicies to state values. For example, with the following component:
const Comp = () => {
const [v1, setV1] = useState('a');
const [v2, setV12] = useState('b');
return <div>Text</div>;
};
When called, React will, internally, now have something like the following:
[ // array of all stateful values for this rendered component
'a', // corresponds to the stateful value of the first useState
'b', // corresponds to the stateful value of the second useState
]
These internal state values are changed when the state setter is called (eg setV1
), and then when the component gets re-rendered, the new stateful values (coming from React internals) are then returned by useState
.
When the state setter is passed a callback, eg, with your
setFullName((prevValue) => {
All that's really needed for this to work is for React to pass the current corresponding state value in React's internals as prevValue
.
When state is set, the corresponding value in React's internals gets updated, but there may be other synchronous code that runs before the component gets re-rendered, and the new values (coming from React internals) get returned by the next invocations of useState
. That's why using the callback form of the state setter sometimes gives different results - the callback argument always comes from React's internals, but the state value returned by useState
only refers to the state at the time the component was rendered.
For example
const [count, setCount] = useState(0);
const clickHandler = () => {
setCount(count 1); // sets the state in React's internals to 1
setCount(count 1); // sets the state in React's internals to 1, not 2;
// because `count` still refers to the initial value of 0
};
const [count, setCount] = useState(0);
const clickHandler = () => {
setCount(count 1); // sets the state in React's internals to 1
setCount(prevCount => prevCount 1); // sets the state in React's internals to 2
// because `prevCount` comes directly from React's internals
};
But, for your code here, because multiple state changes are not occurring in the same render, there's no need to use the callback form - feel free to use the outside fullName
identifier instead of using the prevValue
and a callback.