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

只谈情不闲聊 提交于 2021-02-10 17:45:54

问题


This is part of a larger component but I've summarised it in a reproducible example below:

    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>
        )
    }

So my main issue, is that the mapped data doesn't seem to change with a state update. As a check that state does update, I have a clear button which does clear the data state and the list goes blank. 

When I click the reverse button, I expect the data to be reversed (i.e. "first" to be last and "three" to be in first place). I'm sure my state is updated as I can check it with console logs before and after the reverse button is clicked.

My thought process was to create a completely new reversed array (newData) and set this as the state. However, the mapping doesn't reflect this order change. What am I missing here? 

I understand components in React will rerender when state changes, why does setting a new array to state not trigger this? But the rerender is apparent when clearing the state?

My sandbox for this: https://codesandbox.io/s/immutable-sun-oujqj?file=/src/App.js


回答1:


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

Array.prototype.reverse() reverses the elements in place. You'll need to pass a new array into setData().

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

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



回答2:


The reason React is not re-rendering the component is because Array.prototype.reverse mutates the array and return the reference

For Example

    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]

In the above array === revArray because both are referring to the same array, Since that is the case, The state is not actually changing because the referrence to the array is same.

Solution: Simply return a new Array!

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


来源:https://stackoverflow.com/questions/65689646/reversing-an-array-stored-in-state-doesnt-force-re-render-of-component-in-react

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!