即使使用唯一键,React 也会重新呈现整个组件列表

React re-renders entire list of components even with unique keys

我正在使用 React useState 挂钩来更新项目列表。我只想渲染 added/updated 组件,但每次列表的状态发生变化时,列表中的所有项目都会重新渲染。

我已经按照 Preventing list re-renders. Hooks version. 解决了重新渲染问题,但它不起作用

谁能帮我理解下面的代码有什么问题,或者这实际上不是正确的方法

function App() {

    const [arr, setArr] = useState([])

    useEffect(() => {
        //getList here returns a list of elements of the form {id: number, name: string}
        setArr(getList());
    }, [])

    const clickHandle = useCallback((e, id) => {
        e.preventDefault()
        setArr((arr) => {
            return [...arr, {
                id: id + 100,
                name: `test${id+100}`
            }]

        })
    }, [arr])

    return ( 
    <div className="App">
      {
        arr.map((item) => {
          
          return (
            <NewComp key={`${item.id}`} item={item} clickHandle={clickHandle} />
          );
        })
      }
    </div>
    );
}

const NewComp = ({
    item,
    clickHandle
}) => {
    return ( 
    <div>
        <button onClick={(e) => clickHandle(e, item.id)}>{item.name}</button>
    </div>
    );
}

所有 NewComp 重新渲染的原因是因为只要状态发生任何变化,就会重新创建 clickHandle 函数。

发生这种情况是因为您添加了 arr 作为对 useCallback 的依赖。然而,这不是必需的。

修复后,您可以用 React.memo 包裹 NewComp 以优化它们的重新渲染。您还必须注意,调用组件的渲染函数不同于在 DOM.

中实际重新渲染它
const clickHandle = useCallback((e, id) => {
    e.preventDefault()
    setArr((arr) => {
        return [...arr, {
            id: id + 100,
            name: `test${id+100}`
        }]

    })
}, []);

const NewComp = React.memo({
    item,
    clickHandle
}) => {
    return ( 
    <div>
        <button onClick={(e) => clickHandle(e, item.id)}>{item.name}</button>
    </div>
    );
});