skip to Main Content

I have a component in React with two states using useState. The first one is used to Save the current Object from a form and the other one is used to store all objects by id. To make the code simpler here it is just an array of objects, which also has the same bug.

export default function () {
  const [a, setA] = useState({ hello: "world" });
  const [b, setB] = useState([]);

  const Submit = () => {
    const newB = b;
    newB.push(a);
    setB(newB);
    console.log(b);
  };

  return (
    <>
      <input
        type="text"
        onChange={(event) => {
          setA(Object.assign(a, { hello: event.target.value }));
        }}
      />
      <button onClick={() => Submit()}>Submit</button>
    </>
  );
}

When You submit one first and change the input and then submit again the first object also changes while it is not being altered by this code.

If you change the object in state a to only be a string it works correctly, however in my project I need it to be an object because it has multiple keys.

3

Answers


  1. If your aim is to append a value to the array, you could use the spread operator to set the new value

    So you could instead write the Submit function as

    const Submit = ()=>{
      setB([...b, a]);
    }
    

    ... is known as the spread operator and it opens up the array or object associated with it.

    For example if you have an array B = [{A}, {B}, {C}]
    then ...B = {A}, {B}, {C} and [...B, {D}] = [{A}, {B}, {C}, {D}]

    You could learn more about it here

    Hope this helps!

    Login or Signup to reply.
  2. One way you could copy a object is using the spread operator (…). This will set b to a new array with all the other values of b and add a.

    setB([...b, a]);
    

    For you onChange you can use the same logic. You also might want to add a value prop to the input since it currently is no a controlled input.

    <input
      type="text"
      onChange={(event) => {
        setA({ hello: event.target.value });
      }}
    />
    

    If really want to use Object.assign you can use it like this. Here you assign a new object {} to also a new object with a hello property.

    setA(Object.assign({}, { hello: event.target.value }));
    
    Login or Signup to reply.
  3. setState is asynchronous function, you shouldn’t console.log your state just after setState is called. You copy your array wrong, you need to use spread operator for that. Also your input is not controlled, which means your value is not sync with what is typed in input. Here what I think that should be done:

     const [a, setA] = useState({hello:""})
     const [b, setB] = useState([])
    
     // here may be console.log(b) if you'd like, it would output every render
    
     const Submit = () => {
        setB([...b, a])
      }
    
     return(<>
        <input type="text" 
          value={a.hello}
          onChange={(e) => setA({ hello: e.target.value})} 
        />
        <button onClick={() => Submit()}>Submit</button>
     </>)
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search