0

I'm new to React. I'm having the next problem...

At my functional component I have many states, there are 2 that have the sames fields (one is for an auxiliary operation)

const [fieldsToEdit, setFieldsToEdit] = useState({}); // This one get populated after the first render
const [auxFields, setAuxFields] = useState({.....})

Now, I have a button that calls a function, this functions just edits the 'fieldsToEdit', but it is editing the auxFields too! I realized this writing console.logs after and before of the setState call.

const updateEditHandler = (event) => {
  event.persist());


     setFieldsToEdit((prevState) => {
           const { name, value } = event.target;
           if(name === "fecha_presentacion")
              prevState[name] = value;
           else
              prevState[name] = Number(value);
           return ({
              ...prevState
         });
}

Am I doing it wrong? Hope you can help me.

Patrick Roberts
  • 49,224
  • 10
  • 102
  • 153
  • one thing to remember is don't mutate the `state`. after that you need to put the whole code so we can see what's going on there –  Jan 21 '21 at 16:52

2 Answers2

3

You should not mutate state. Instead create a new object without modifying the previous one.

prevState[name] = value; 
return { ...prevState };

The above first mutates the previous state, then returns a copy of it. Instead return a copy that contains the new value without modifying the previous state.

return { ...prevState, [name]: value };

The above copies the previous state and adds or overrides the (evaluated) name property with value. This is all done without mutating prevState.

Applying this to your actual code you would get the following.

setFieldsToEdit((prevState) => {
  const { name, value } = event.target;
  
  if (name == "fecha_presentacion") {
    return { ...prevState, [name]: Number(value) };
  } else {
    return { ...prevState, [name]: value };
  }
});

// or (depending on preference)
setFieldsToEdit((prevState) => {
  let { name, value } = event.target;
  if (name == "fecha_presentacion") value = Number(value);
  return { ...prevState, [name]: value };
});
3limin4t0r
  • 19,353
  • 2
  • 31
  • 52
  • I've never seen the `useState` hook's `set` function take another function as a parameter before. I would have assumed that this would have set `fieldsToEdit` to the function, not executed it and saved the returned value? – DBS Jan 22 '21 at 10:56
  • @DBS If the new state is computed using the previous state you should pass a callback. See the [`useState` - Functional updates](https://reactjs.org/docs/hooks-reference.html#functional-updates) and [`setState`](https://reactjs.org/docs/react-component.html#setstate) documentation. – 3limin4t0r Jan 22 '21 at 13:02
  • Ah cool, I looked through the docs and clearly completely missed the relevant section. Good to know that that's an option. Thanks. – DBS Jan 22 '21 at 13:27
  • Why shouldn't I mutate the state? (Sorry for the ignorance). I will try this solution in some days because I'm starting my holidays, I will give you notice at my comeback :) – Nicolas Villacorta Jan 22 '21 at 15:34
  • @NicolasVillacorta [Why can't I directly modify a component's state, really?](https://stackoverflow.com/questions/37755997/why-cant-i-directly-modify-a-components-state-really) – 3limin4t0r Jan 22 '21 at 17:23
  • It worked! @3limin4t0r !!! Sorry for the late on answer, I've been with many other projects. Can you tell me why you writing "name" in brackets "[name]" at return? What is the difference between using them or not? – Nicolas Villacorta Apr 23 '21 at 16:52
  • 1
    @NicolasVillacorta Without brackets the variable is not evaluated and it becomes the literal `name` instead of the contents of the variable `name`. See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Object_initializer#computed_property_names – 3limin4t0r Apr 23 '21 at 16:57
-1
     setFieldsToEdit((prevState) => {
       const { name, value } = event.target;
       if(name === "fecha_presentacion")
          prevState[name] = value;
       else
          prevState[name] = Number(value);
       return ({
          ...prevState
     });

In prevState[name] = you mutating the state. You need to clone it and set it with either lodash deepClone or JSON.stringify and then JSON.parse if you are not familiar with lodash. You are not sharing your code so useState({.....}) does not mean anything. But from the general picture I am getting from your code I think that fieldsToEdit and auxFields have the same reference so because you prevState[name] = you are changing both Try to not mutate your state in any framework

Morpheus
  • 421
  • 1
  • 4
  • 13