[英]State is not updated properly when using React.memo and useCallback
我的問題很常見,但要弄清楚我的示例有什么問題並不容易。 我有嵌套組件 Parent->Child1->Child2。 State 和 setState 在 props 中傳遞給子組件。 我想避免在更新父組件時重新渲染子組件,並且我想避免在僅更改一項時重新渲染整個列表。
這是我的示例https://plnkr.co/edit/6nKaKrgNIF7LSetN正如您所看到的,當我更改 Parent 中的標題或 Child1 中的描述時,Child2 不會重新呈現,但是當我在 Child2 中更改 state 時,整個列表是重新渲染加上 state 更新有一些副作用。
父組件。 它包含標題和。 對於 Child1 onChange,我收到了我想在 state 中更新的道具和它的價值。 我使用 useCallback 鈎子來避免子組件中的額外重新渲染,你會在那里看到 React.memo
const Parent = ({ initialData }) => {
const [data, setData] = React.useState(initialData);
console.log('render Parent');
return <>
<h2>Parent</h2>
<input
placeholder="title"
value={data.title}
onChange={
React.useCallback((e) => {
setData(prev => ({ ...prev, title: e.target.value }))
}, [])
}
/>
<br />
<Child1
data={data}
onChange={
React.useCallback((prop, value) => {
setData(
prev => {
prev[prop] = value;
const newState = { ...prev };
return newState;
}
);
}
, []
)
}
/>
</>
}
然后在用 React.memo 包裹的 Child1 中。 它還在列表中呈現 Child2。
const Child1 = React.memo(
({ data, onChange }) => {
console.log('render Child1');
return <>
<h3>Child1</h3>
<input
placeholder="description"
value={data.description}
onChange={(e) => { onChange('description', e.target.value) }}
/>
<br />
<br />
<br />
{data.list.map((element, index) => {
return <Child2
key={index} // don't do this in real
index={index}
data={element}
onChange={
React.useCallback(
(prop, value) => {
const newList = data.list.map((e, i) => {
let newItem = { ...e };
if (i == index) {
newItem[prop] = value;
}
return newItem;
});
onChange('list', newList);
}
,
[]
)
}
/>
})}
</>
}
)
Child2 在列表中呈現
const Child2 = React.memo(({ index, data, onChange }) => {
console.log('render Child2', index);
return (
<>
<h4>Child2</h4>
Country: <br />
<input
placeholder="country"
value={data.country}
onChange={(e) => onChange('country', e.target.value)}
/>
<br />
<br />
Region: <br />
<input
placeholder="region"
value={data.region}
onChange={(e) => onChange('region', e.target.value)}
/>
<br />
<br />
City: <br />
<input
placeholder="city"
value={data.city}
onChange={(e) => onChange('city', e.target.value)}
/>
<hr />
</>
)
}
)
Child2 中的onChange
正在從 Parent 調用setData
,這會更新 Parent 的 state。 更新 Parent 的 state 將觸發重新渲染。 Child1 重新渲染是因為它的data
prop 正在改變(改變 props 也會觸發重新渲染)。
嘗試在 Parent 和 Child1 的 useCallback 函數中傳遞您的依賴項 arrays 中的title
,看看是否有效。 這應該使 onChange function 看起來正在“改變”,這應該會觸發組件樹的重新渲染。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.