简体   繁体   中英

React DID NOT update components after update list state (by hook)

When use useState hook to store list of object (ex. [{ a:1 }, { a:2 }]), If I change list's element(object)'s content, react DO NOT update component.


For example in below code,

If I press first button, first h1 component's content will be 24. BUT even though I press first button, first h1 component component DO NOT update.

If I press second button after press first button, component DO update.

const [tempList, setTempList] = useState([
  { a: 1 },
  { a: 2 }
])


return (
  <div>
    {
      tempList.map((item, idx) => {
        return <h1>{item.a}</h1>
      })
    }
    <button onClick={() => {
      let temp = tempList;
      temp[0]['a'] = 24
      setTempList(temp)
    }}>modify list</button>
    <button onClick={() => {setTempList(...tempList, {a: 3})}}>insert list</button>
  </div>
)

I already used useReducer hook. But it is not solution. How Can I update component?

React re-render the component when the state or props change. And it determines that the state has changed by only looking at the memory address of the state.

In the callback of the first button, by declaring the variable temp , you are only creating a shallow copy of the tempList array. Therefore, even after modifying the first object, the id of the array does not change and react does not know that the state have been changed.

And also, by putting a callback in the setState function, you can always have a fresh reference to the current state:

const [state, setState] = useState(0);
setState(state+1) <-- the state can be stale
setState(state=>state+1) <-- increment is guaranteed

Try building an another array:

<button onClick={()=>{
  setTempList(tempList=>tempList.map((item,ind)=>{
    if(ind===0){
      return {a:24};
    }
    else{
      return item;
    }
  })
}}>modify list</button>

You had a syntax error in the second callback. In addition to the fix, I recommend again to put a callback function to the setTempList function.

<button onClick={() => {
  setTempList(tempList=>[...tempList, {a: 3}])
}}>insert list</button>

You seems to be updating same reference of object instead of pushing a new object. Try this -

const [tempList, setTempList] = useState([
  { a: 1 },
  { a: 2 }
])


return (
  <div>
    {
      tempList.map((item, idx) => {
        return <h1>{item.a}</h1>
      })
    }
    <button onClick={() => {
      let temp = [...tempList];
      temp[0] = { a: 24 };
      setTempList(temp)
    }}>modify list</button>
    <button onClick={() => {setTempList(...tempList, {a: 3})}}>insert list</button>
  </div>
)

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