React/react hooks: child component is not re-rendering after the state is changed?

后端 未结 3 1110
灰色年华
灰色年华 2021-01-25 22:29

I am writing a code in react/react hooks that attempt to do the following.

Get an array of objects from the parent component as a prop Set it as a state using useS

相关标签:
3条回答
  • 2021-01-25 23:08

    array::sort

    The sort() method sorts the elements of an array in place and returns the sorted array. The default sort order is ascending, built upon converting the elements into strings, then comparing their sequences of UTF-16 code units values.

    What this means for you is the order of elements stored in an array may change, but the array is sorted in place which means the same array reference is returned (unlike other array functions that return new arrays).

    React reconciliation occurs by examining state and props and makes a holistic assumption that if the next state/prop references haven't changed then the values haven't changed and thus returns the last computed rendered DOM. This is the important detail of updating react state... each update needs to reference a new object.

    In your case you are merely saving the reference to the current array in state, mutating it, and resaving it. Since the reference is stable and doesn't change, react doesn't re-render.

    const otc = () => {
      let k = newarray; // <-- saved array reference!!
      setnewarray(k.sort((a, b) => (a.time > b.time) ? -1 : 1 ));
    }
    

    The correct react way is to copy the current array values into a new array so it will have a new object reference.

    const otc = () => {
      const newSortedArray = [...newArray].sort(
        (a, b) => (a.time > b.time) ? -1 : 1
      ); // spread old array values into new array, then sort
      setNewArray(newSortedArray);
    }
    
    0 讨论(0)
  • 2021-01-25 23:08

    React checks for changes in props and state by doing a shallow object equality check. If you set the state to the same object you received from state, React assumes you aborted your change and doesn't do anything, even if the properties on the object changed.

    The key is that the sort() method sorts the array in place, and returns a reference to the same array. So React sees it as the same array object, even though the orser of its entries is different.

    The solution is to create a new array:

    let k = [...newarray];
    

    When k is passed to setnewarray, React sees that it is an entirely different object, and triggers the rerender.

    0 讨论(0)
  • 2021-01-25 23:16

    Sort() work in place, which means you won't get what you want via directly return.

    By the way, you can write the sort() in a better format as below

    const otc = () => {
      const result = [...newarray];
      result.sort((a, b) => b.time - a.time);
      setNewarray(result);
    };
    const orc = () => {
      const result = [...newarray];
      result.sort((a, b) =>
        a.rating !== b.rating ? b.rating - a.rating : b.time - a.time
      );
      setNewarray(result);
    };
    

    Try it online here:

    0 讨论(0)
提交回复
热议问题