gpt4 book ai didi

javascript - 如何避免在父组件状态更新时重新渲染循环中的所有子组件

转载 作者:行者123 更新时间:2023-12-03 23:01:12 25 4
gpt4 key购买 nike

我有一个子组件,它位于父组件的循环内。当其中一个子组件正在更新父组件的状态时,它会重新渲染所有子组件,因为它是循环的。我怎样才能避免每次迭代的重新渲染。


function Parent() {
const [selectedChild, setSelectedChild] = useState([]);

const onChangeHandle = (event, id) => {
const checked = event.target.checked;
let updatedArray = [...selectedChild];
if(checked){
if(!selectedChild.includes(id)){
updatedArray.push(id);
}
}
else{
var index = updatedArray.indexOf(id)
if (index !== -1) {
updatedArray.splice(index, 1);
}
}
setSelectedChild(updatedArray);
}
const dummy = (id) => {
return selectedChild.includes(id);
}
return (
<div>
<table>
<tbody>
{[1,2,3].map((value, index) => {
return (
<Child
key={index}
index={index}
value={value}
handle={onChangeHandle}
isSelected={dummy}
/>
)
})}
</tbody>
</table>
<div>
{selectedChild}
</div>
</div>)
}

function Child({index, value, handle, isSelected }) {
console.log('rendering')

return (
<tr>
<td>
<input
type="checkbox"
checked={isSelected(index)}
onChange={(event) => handle(event, index)}/>
</td>
<td>hello {index} {value}</td>
</tr>
)
}

export default function App() {
return (
<div className="App">
<Parent />
</div>
);
}
当前行为:
在上面的代码中,当我单击其中一个子组件中的复选框时,它正在更新父组件状态( selectedChild)。所以循环正在执行,所有子项(所有表行)都在重新渲染。
预期行为:
只有那个特定的行必须重新渲染
演示: https://codesandbox.io/s/newpro-0pezc

最佳答案

为此,您可以使用 React.memo如果 Prop 保持不变,它将记住您的组件。但是鉴于您的代码,您需要进行一些额外的更改:

  • 你必须申请useCallback记住 onChangeHandle 函数;
  • 要正确记住 onChangeHandle,您需要对其进行重构。你不能通过selectedChild直接,否则它会记住它的值。使用 setSelectedChild将接受 selectedChild 的函数作为参数传递反而。
  • 您的 child 应该收到 isSelected作为 bool 值而不是函数。否则 props 将保持不变,并且 Child 永远不会更新;
    import React, { useState, memo, useCallback } from "react";

    function Parent() {
    const [selectedChild, setSelectedChild] = useState([]);

    const onChangeHandle = useCallback((event, id) => {
    setSelectedChild(selectedChild => {
    const checked = event.target.checked;
    let updatedArray = [...selectedChild];
    if (checked) {
    if (!selectedChild.includes(id)) {
    updatedArray.push(id);
    }
    } else {
    var index = updatedArray.indexOf(id);
    if (index !== -1) {
    updatedArray.splice(index, 1);
    }
    }
    return updatedArray;
    });
    }, []);

    const dummy = id => {
    return selectedChild.includes(id);
    };

    const renderChildren = () =>
    [1, 2, 3].map((value, index) => {
    return (
    <Child
    key={index}
    index={index}
    value={value}
    handle={onChangeHandle}
    isSelected={dummy(index)}
    />
    );
    });

    return (
    <div>
    <table>
    <tbody>{renderChildren()}</tbody>
    </table>
    <div>{selectedChild}</div>
    </div>
    );
    }

    const Child = memo(({ index, value, handle, isSelected }) => {
    console.log("rendering");

    return (
    <tr>
    <td>
    <input
    type="checkbox"
    checked={isSelected}
    onChange={event => handle(event, index)}
    />
    </td>
    <td>
    hello {index} {value}
    </td>
    </tr>
    );
    });

    export default function App() {
    return (
    <div className="App">
    <Parent />
    </div>
    );
    }

  • https://stackblitz.com/edit/so-memo-children?file=src/App.js

    关于javascript - 如何避免在父组件状态更新时重新渲染循环中的所有子组件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65630212/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com