gpt4 book ai didi

reactjs - 在 React.memo 中使用 React 功能组件时如何解决闭包问题?

转载 作者:行者123 更新时间:2023-12-04 13:00:14 25 4
gpt4 key购买 nike

我正在将 React 功能组件与 React.memo 一起使用,但我遇到了一个问题,在我看来,该问题源自 JavaScript 闭包。
(我也使用 Immer 来实现不变性,但我相信它不会影响情况。)

以下是情况的简化版本:

import React, { useState } from 'react';
import produce from "immer";

const initialData = [
{id: 1, value: 0},
{id: 2, value: 0},
{id: 3, value: 0}
]

const ChildComponent = memo(
({ value, onChange }) => (
<p>
<input value={value} onChange={onChange} type="number" />
</p>
),
(prevProps, nextProps) => prevProps.value === nextProps.value
);

const ParentComponent = props => {
const [data, setData] = useState(initialData);

const onDataChange = id => event => {
setData(
produce(data, draft => {
const record = draft.find(entry => entry.id === id);
record.value = event.target.value;
})
);
};

return data.map(record => (
<ChildComponent
key={record.id}
value={record.value}
onChange={onDataChange(record.id)}
/>
));
};

我正在使用 React.memo 来避免对其值没有改变的 ChildComponents 进行不必要的重新渲染,但是这样 ChildComponent 正在存储 onChange 函数的旧版本,它(在我的理解中由于 JavaScript 闭包)引用了旧版本的数据。

这样做的结果是,当我最初更改第一个 ChildComponent 的值,然后更改另一个 ChildComponent 的值时,第一个 ChildComponent 的值将恢复为初始值。

可以在 this sandbox 中找到该情况的再现。 .

在网上搜索后,我发现这个问题的解决方案是在 onChange 函数中使用 ref 来获取最新数据,如下所示:
const ParentComponent = props => {
const [data, setData] = useState(initialData);
const dataRef = useRef();
dataRef.current = data;

const onDataChange = id => event => {
setData(
produce(dataRef.current, draft => {
const record = draft.find(entry => entry.id === id);
record.value = event.target.value;
})
);
};

return data.map(record => (
<ChildComponent
key={record.id}
value={record.value}
onChange={onDataChange(record.id)}
/>
));
};

可以找到具有此解决方案的沙箱 here .

这解决了这个问题。但是我想问, 这是正确的解决方案吗 ?或者我是否以错误的方式使用 React 和 React Hooks?

最佳答案

尽管使用引用是一个有效的解决方案,但您应该使用 functional setState .

If the new state is computed using the previous state, you can pass a function to setState. The function will receive the previous value, and return an updated value.


const onDataChange = id => event => {
event.persist();
setData(data =>
produce(data, draft => {
const record = draft.find(entry => entry.id === id);
record.value = event.target.value;
})
);
};

Edit sparkling-haze-e9y22

关于reactjs - 在 React.memo 中使用 React 功能组件时如何解决闭包问题?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58993337/

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