0

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.

2
  • you need to bind the input.value to the corresponding piece of state Commented Apr 23, 2020 at 21:27
  • @AngelSalazar i did using the handler to get the values, but if i set the input value like this <input onChange={inputs_handler} type='text' value={input_values.input1} name='input3' /> i woudn't be able to change the value Commented Apr 23, 2020 at 21:29

1 Answer 1

2

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

Sign up to request clarification or add additional context in comments.

4 Comments

this cleared the inputs values, but the problem is that it changes the structure of the input_value object. please set console.log(input_values) in the handler and see how the input_values structure is changed when type three letters in the first input
@AliAlAmine Oof, yes, you are quite right. I updated answer with solution that doesn't change the shape of state.
just didn't get how this set_input_value({ ...input_value, [name]: value }); solved it, can you provide a good resource link that explains this in a simple and clear example?
@AliAlAmine Sure. Updated answer again with some explanation and link to react and javascript docs.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.