Ali
Ali

Reputation: 1759

How to empty input values and reset state in ReactJS hooks

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

Answers (1)

Drew Reese
Drew Reese

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>
);

Edit romantic-hawking-rqvko

Upvotes: 2

Related Questions