Reputation: 36
I have a question about the useState hook. We all know that the useState setter method is not reflecting a change immediately. For example,
const App = () => {
const [name, setName] = React.useState("");
return (
<React.Fragment>
<form onSubmit={(e) => {
e.preventDefault();
setName("submit");
console.log("onSubmit:",name)
}}
className="form">
<div>
<input type="text" />
</div>
<button type="submit">add </button>
</form>
</React.Fragment>
);
};
ReactDOM.render(<App />,document.getElementById("root"))
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.development.js"></script>
When one inputs some words and clicks ADD, nothing presents after "onSubmit:" in the console. The reason is that the setter setName() is not reflecting a change immediately. However, if the setter method is implemented in the onChange property, the change can be applied immediately by setName(). For example, if we move setName() from onSubmit to onChange in the input element.
const App = () => {
const [name, setName] = React.useState("");
return (
<React.Fragment>
<form onSubmit={(e) => {
e.preventDefault();
console.log("onSubmit:",name)
}}
className="form">
<div>
<input
type="text"
onChange={(e) => {
setName(e.target.value);
}}
/>
</div>
<button type="submit">add </button>
</form>
</React.Fragment>
);
};
ReactDOM.render(<App />,document.getElementById("root"))
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.development.js"></script>
console.log() is going to print out some words we input after "onSubmit:". Is it true that setter method is going to be immediately applied in the onChange property? Or do I misunderstand some details about React useState setter method? I reviewed several qeustions about React useState setter from Stackoverflow. They seem not to be directly related to my problem. Thanks a lot.
Upvotes: 1
Views: 704
Reputation: 186
if the setter method is implemented in the onChange property, the change can be applied immediately by setName()
I am not sure what you mean by immediately here, but, no, in neither case is the change applied 'immediately'
the way the setter
of useState
works is, once the 'setting' is done, the component re-renders, and in this process the component becomes 'aware' of the newly set value.
So, in case number 1, where you setName
in onSubmit
, and immediately after, you console.log
, well, the console.log
fires before the component has re-rendered, and hence it is not 'aware' of the new value against name
in case number 2, everytime onChange
fires, you are setting name
-> which is re-rendering the component, and making onSubmit
'aware' of the new name
value. So then, when you finally press the submit button and trigger onSubmit
, it is already 'aware' of the latest name
value, and console.log
s it accordingly.
Hopefully that paints a picture for you on how state update works in react.
Upvotes: 3