反转存储在 State 中的数组不会强制在 React 中重新渲染组件

Reversing an array stored in State doesnt force re-render of component in React

这是一个更大组件的一部分,但我在下面的可重现示例中对其进行了总结:

    import React, {useState} from 'react'

   
    function App() {
        const [data,setData] = useState([{name:'first'},{name:'second'},{name:'three'}])

       // Function to reverse a given array
        const reverseArray = (array) => {
          var reverseArray = array.reverse();
          return reverseArray;
        }


        return (
            <div>
                  {data.map((item,index)=>{
                         return <h1 key={index}>{item.name} index: {index}</h1>
                    })}
            

                    {/*When I click this I expect the div above to rerender */}
                    <button onClick={()=>{
                        var newData = data;
                        setData(reverseArray(newData))}
                    }>
                      Reverse Order
                     </button>

                    {/* Logs state to the console to check order is reversed */}
                    <button onClick={()=>console.log(data)}>Log Data</button>

                    {/* Clearing the state by setting to empty array */}
                    <button onClick={()=>setData([ ])}>Clear Data</button>

                    
            </div>
        )
    }

所以我的主要问题是映射数据似乎不会随着状态更新而改变。 作为状态更新的检查,我有一个清除按钮,它清除数据状态并且列表变为空白。

当我点击反向按钮时,我希望数据被反向(即“第一”在最后,“三”在第一位)。 我确定我的状态已更新,因为我可以在单击反向按钮前后使用控制台日志检查它。

我的想法是创建一个全新的反向数组 (newData) 并将其设置为状态。但是,映射不反映此顺序更改。我在这里错过了什么?

我知道 React 中的组件会在状态改变时重新渲染,为什么设置一个新的状态数组不会触发这个?但是清除状态时重渲染很明显?

我的沙箱:https://codesandbox.io/s/immutable-sun-oujqj?file=/src/App.js

演示: https://codesandbox.io/s/array-reverse-react-state-0v67h

Array.prototype.reverse() 反转原位的元素。您需要将一个新数组传递到 setData().

<button
  onClick={() => {
    var newData = data;

    // Create a new array using the spread operator
    setData(reverseArray([...newData])); 
  }}
>

React 不重新渲染组件的原因是因为 Array.prototype.reverse 改变了数组和 return 引用

例如

    const array = [1,2,3,4,5]
    const revArray = array.reverse() // This will reverse 'array' variable and returns it's reference
    
    array === revArray // this statement is true
    console.log(array) // result [5,4,3,2,1]
    console.log(revArray) // result [5,4,3,2,1]

在上面array === revArray因为两者都指的是同一个数组, 既然如此,状态实际上并没有改变,因为对数组的引用是相同的。

解法: 只需 return 一个新数组!

 const reverseArray = (array) => {
      const revArray = array.reverse();
      return [...revArray] 
    }