简体   繁体   中英

updating state using hooks in array of objects

I want to change active to true in my object, in the console log i have an updated version of the state however i cannot update the state itself, i feel im going about this the wrong way. any help would be fantastic thankyou, for sure there is a similar post somewhere but i have failed to find anything.

const [components, setComponents] = useState([
  {
    compName: "Weather",
    path: 'weather',
    active: false
  },
  {
    compName: "Tasks",
    path: 'tasks',
    active: false
  },
])
                                                      

 function onActivateHandler(){
      setComponents((prevComponents) => {
        const copy = [...prevComponents]
        let newState = {...copy[1]}
        newState.active = true
        console.log(newState)
    
        return  {...prevComponents}
      })
 }

I think that you just only need to generate a new reference for the whole array.

Another thing that I noticed is that you are returning an object from your setComponents() function. Since the state variable components is an array, i think you need to return an array.

Also, write onActivateHandler() method as an arrow function to bind it to the component context, just in case, normally is what you would want to do.

I would write it like this (I toggle the active value justo to demonstrate):

const myComponent = () => {
    const [components, setComponents] = useState([
        {
           compName: "Weather",
           path: "weather",
           active: false,
        },
        {
           compName: "Tasks",
           path: "tasks",
           active: false,
        },
    ]);

    const onActivateHandler = () => {
        setComponents((prevComponents) => {
           // update the array reference
           const newState = [...prevComponents];
           newState[1].active = !newState[1].active;

           // Your state variable is an array,
           // so you need to return an array
           return [...prevComponents];
        });
    };

    return (
        <>
            <button onClick={onActivateHandler}>Click</button>
            <div>{components[1].active ? 'active' : 'inactive'}</div>
        </>
    )
};

As lawrence-witt say below not creating a new object inside the new array may lead to not re-rendering in some cases, but in your simple case the code above works fine, since is the array reference what react is tracking on, and not the reference of the objects inside. You can spread the newState[1] into a new object if you need to, but you will need to delete the older one form the state array.

Cheers!

You just have to return your cloned, modified object alongside the rest of the prevComponents . At the moment you are returning just the old state, so nothing will change (apart from the fact that you are accidentally returning an object, not an array).

Edit: doesn't look so pretty now but it is safe.

function onActivateHandler(){
    setComponents((prevComponents) => {
      const copy = [...s];
      const newState = {...copy.splice(1, 1)[0]}
      newState.active = true;
      return [...copy, newState];
    })
 }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM