对道具深度变化做出反应更新

时间:2021-04-04 13:49:42

标签: javascript reactjs

我有一个组件,它将矩阵作为输入(实际上是一个具有矩阵、getter 和 setter 的对象,但这无关紧要)并基于它呈现一个表。表格单元格应该是文本输入,并且应该在更改其中的值时更改矩阵。如何在不使用强制更新的情况下做到这一点?这是示例工作代码(这是 create-react-app 中的 App.js):

    val floatAnimation = animateFloatAsState(
        targetValue = 1f,
        animationSpec = infiniteRepeatable(
            animation = tween(durationMillis = 2000, easing = LinearEasing),
        )
    )

您可以通过以下链接在 CodePen 上试用:https://codepen.io/askenderski/pen/dyNRyxJ

3 个答案:

答案 0 :(得分:1)

因此,如果您的事实来源来自上面(道具而不是状态),那么您还需要传递一个处理程序:

const SomeParentComponent = () => {
   // making an assumption that the immediate parent
   // holds the nodes as state - it could come from anywhere
   // "above" your component
   const [matrix,setMatrix] = useState(theMatrix);

   // this is the handler that will update your state
   const handleChangeNode = (i,j) => {
   
     // always reurn a new matrix, which is why you do matrix.map
     setMatrix(matrix => matrix.map((row,idx) => {

       // not interested in changing this one, return the same reference
       if(idx !== i) return e;

       // change this one
       return row.map((col,idx2) => {
         // not interested in changing this one
         if(idx2 !== j) return col;

         // change this one
         return col++;
       });
     });
   }

   return <YourComponent nodes={matrix} handleChangeNode={handleChangeNode}/>
}

不要在反应中改变东西。如果要更新对象/数组(或嵌套在该对象/数组中的某些属性),请始终返回一个新对象/数组。

答案 1 :(得分:1)

我认为正确的方法是将 nodes 作为一个状态并将它和一个 setNodes 作为道具传递给您的 Component,然后从您的孩子喜欢这样(记下 newNode 作为 nodes 的副本):-

    
    function Component({nodes,setNodes}) {  
  
        const handleOnClick = (i,j) => {
          let newNodes = nodes.map(row=>[...row]);
          newNodes[i][j]+=1;
          setNodes(newNodes);
        };
    
        return (
            <thead>
                {nodes.map((row,i)=>
                    <tr>
                        {row.map((el,j)=>
                            <td onClick={()=>handleOnClick(i, j)}>{el}</td>
                        )}
                    </tr>
                )}
            </thead>
        );
    }
    
    function App() {
        const [nodes,setNodes] = React.useState([
        [1,2,3],
        [4,5,6],
        [7,8,9]
    ]);
        return ( <Component nodes={nodes} setNodes={setNodes} />
        );
    }

ReactDOM.render(
  <App></App>,
  document.getElementById('root')
);

答案 2 :(得分:0)

只需useState就足够了

Demo link

  const [nodeList,setNodeList] = React.useState(nodes);
    
        const handleOnClick = (i,j) => {
            let nodesCopy = [...nodeList];
            nodesCopy[i][j]++;
            setNodeList(nodesCopy)
        };