反应 setState() 不触发重新渲染

Bor*_*nov 4 javascript reactjs react-hooks

我有从其他文件接收数据并设置为状态的组件:

const [sortedPlans, setSortedPlans] = useState(
    data.Plans.sort((a, b) => b.IndustryGrade - a.IndustryGrade)
  );//data is from external file
Run Code Online (Sandbox Code Playgroud)

设置状态、对数据进行排序并渲染初始屏幕后,我有一个函数可以在调用时对排序计划进行排序:

const sort = (event) => {
    console.log(event);
    const newArr = sortedPlans.sort((a, b) => {
      return b[event] - a[event];
    });
    console.log(newArr);
    return setSortedPlans(newArr);
  };
Run Code Online (Sandbox Code Playgroud)

问题是这永远不会触发组件的重新渲染。我希望当我设置新状态时能够在 jsx 中看到它。为什么当我 console.log(newArr) 时结果已正确排序,但状态的此设置未触发重新渲染?这是沙箱:

https://codesandbox.io/s/charming-shape-r9ps3p?file=/src/App.js

Rei*_*r68 20

给你:Codesandbox 演示

您应该首先制作要修改的数组的浅表副本。然后将该数组设置为新状态。然后它重新渲染组件,您就可以根据需要进行过滤。

  const sort = (event) => {
    console.log(event);
    //shallow copying the state. 
    const newArr = [...sortedPlans];

    //modifying the copy
    newArr.sort((a, b) => {
      return b[event] - a[event];
    });
    console.log(newArr); //results here are correctly sorted as per event
    
    //setting the state to the copy triggers the re-render.
    return setSortedPlans(newArr);
  };
Run Code Online (Sandbox Code Playgroud)

  • React 会使用严格比较 `===` 与之前的状态进行比较,以决定是否启动重新渲染。对于同一个对象(或者从技术上来说也是一个对象的数组),`===` 会返回 true。突变后,对象(或数组)在技术上保持不变,尽管在您的情况下发生了突变(即字段被更改)或排序。事实上,`arr = []; arr.sort(); arr === arr` (4认同)
  • 只要状态或属性发生变化,React 组件就会自动重新渲染。在您的示例中,“sortedPlans.sort”正在对数组进行排序并返回完全相同的数组,因此您实际上从未更新状态。最简单的方法是复制状态,修改副本,然后将状态设置为等于副本,然后更新状态并重新渲染组件。 (2认同)