Reputation: 1759
Assume I have three inputs and a button, I want to empty input values when button is clicked.
const [input_value,set_input_value] = useState({
input1:'',
input2:'',
input3:''
})
const inputs_handler = (e) => {
let name= e.target.name;
let value= e.target.value;
input_value[name] = value;
set_input_value(input_value);
}
const clear_input_values = () => {
// First try
/*
set_input_value({
input1:'',
input2:'',
input3:''
})
*/
//SECOND TRY
set_input_value(prevState => ({
...prevState,
input1:'',
input2:'',
input3:''
}))
// console.log shows that the values of state didn't get empty from the first click, but does in
the second
console.log(input_value)
}
<div>
<input onChange={inputs_handler} type='text' name='input1' />
<input onChange={inputs_handler} type='text' name='input2' />
<input onChange={inputs_handler} type='text' name='input3' />
<input onClick={clear_input_values} type='submit' />
</div>
I can use document.getElementsById(id)[0].value='';
to empty the input's value but I don't think this is the proper way to do it in a React project.
This is really confusing me, i appreciate if someone provides a clear example or a link to an example that explains how the state works and when it does render the component. since i believe i changed the state value before i use set_inputvalues()
method.
Upvotes: 0
Views: 2057
Reputation: 202605
Issue is state object mutation. You are mutating input_value
and saving it back in state instead of returning a new object reference.
Updating State
set_input_value(input_value);
vs set_input_value({ ...input_value, [name]: value });
This spreads in the existing state and sets the key-value pair of the input that was updated.
If the spread syntax is unfamiliar it is a common convention to shallowly copy the state object into a new object. useState
hooks can also use functional updates, and if you check the link you'll see a note about how useState
doesn't merge in state updates like it's class-based counterpart, this.setState()
:
Note
Unlike the
setState
method found in class components,useState
does not automatically merge update objects. You can replicate this behavior by combining the function updater form with object spread syntax:setState(prevState => { // Object.assign would also work return {...prevState, ...updatedValues}; });
You might notice now that our solution isn't a functional update, but the spread syntax works the same. The reason we can do a standard update is because your state consists of 3 independent variables, and upon each update you copy all of them and then simply replace any one of them.
Functional updates are primarily used when the next state value depends on the current state value, like the counter examples react loves to use.
I should point out that functional updates are a react convention while the spread syntax is part of javascript's expressions & operators.
Clearing Inputs
Your first try is correct for clearing state, so long as you bind the state value to each input.
const [input_value, set_input_value] = useState({
input1: "",
input2: "",
input3: ""
});
const inputs_handler = e => {
let name = e.target.name;
let value = e.target.value;
set_input_value({ ...input_value, [name]: value });
};
const clear_input_values = () => {
set_input_value({
input1: "",
input2: "",
input3: ""
});
};
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<h2>Start editing to see some magic happen!</h2>
<div>
<input
onChange={inputs_handler}
type="text"
name="input1"
value={input_value.input1}
/>
<input
onChange={inputs_handler}
type="text"
name="input2"
value={input_value.input2}
/>
<input
onChange={inputs_handler}
type="text"
name="input3"
value={input_value.input3}
/>
<input onClick={clear_input_values} type="submit" />
</div>
</div>
);
Upvotes: 2