[英]A functional subcomponent doesn't rerender on props change
我有一個非常重的(計算上的)功能組件(父),它沒有狀態,並且具有本地狀態的子組件很少。 孩子只依賴於從父母發送的道具。
我將一個函數傳遞給其中一個孩子 (ChildA) 以更改 Parent 上變量的值。
此變量是不同子組件 (ChildB) 的道具之一,它具有基於該道具的狀態並在 useEffect 鈎子中更新它。
當作為 prop 傳遞的值在 Parent 組件上發生更改時,ChildB 組件不會重新渲染。
當然,在 Parent 上引入狀態(useState 鈎子)修復了這個問題,但會一遍又一遍地重新渲染父級並殺死性能,因為 Parent 有 500 多個嵌套組件,這些組件都被重新渲染。
引入某種類型的 Store(Redux、MobX)可能會解決這個問題,但這將是一種矯枉過正。
一個簡化的例子:
import React, { useEffect, useState } from "react";
export default function App() {
return <Parent />
}
const ChildA = ({ onAction }) => {
return <button onClick={onAction}>CLICK</button>;
};
const ChildB = ({ coreValue }) => {
const [value, setValue] = useState(0);
useEffect(() => {
setValue(coreValue);
}, [coreValue]);
return <div>My value: {value}</div>;
};
const Parent = () => {
let calculatedValue = 0;
const changeValue = () => {
calculatedValue += Math.random();
};
return (
<div>
<ChildA onAction={changeValue} />
<ChildB coreValue={calculatedValue} />
</div>
);
};
你可以在這里測試代碼: https : //codesandbox.io/s/vigilant-wave-r27rg
如何在道具更改時僅重新渲染 ChildB?
您必須將值存儲在父組件狀態中,並將父組件狀態值發送到 ChildB,在那里您不需要維護狀態和 useEffect 鈎子來捕獲更改。 請參閱此處的代碼: https : //codesandbox.io/s/adoring-chatelet-sjjfs
import React, { useState } from "react";
export default function App() {
return <Parent />;
}
const ChildA = ({ onAction }) => {
return <button onClick={onAction}>CLICK</button>;
};
const ChildB = ({ coreValue }) => {
return <div>My value: {coreValue}</div>;
};
const Parent = () => {
const [value, setValue] = useState(0);
const changeValue = () => {
setValue(value + Math.random());
};
return (
<div>
<ChildA onAction={changeValue} />
<ChildB coreValue={value} />
</div>
);
};
React 的useCallback
和memo
防止了不必要的重新渲染。 請注意,無論Parent
或ChildB
狀態更改的次數如何,ChildA 都不會重新呈現。 此外,當前的例子並不需要useState
/ useEffect
在ChildB
https://codesandbox.io/s/usecallback-and-memo-ptkuj
import React, { useEffect, useState, memo, useCallback } from "react";
export default function App() {
return <Parent />;
}
const ChildA = memo(({ onAction }) => {
console.log("ChildA rendering");
return <button onClick={onAction}>CLICK</button>;
});
const ChildB = memo(({ coreValue }) => {
const [value, setValue] = useState(0);
useEffect(() => {
setValue(coreValue);
}, [coreValue]);
return <div>My value: {value}</div>;
});
const Parent = () => {
const [calculatedValue, setCalculatedValue] = useState(0);
const changeValue = useCallback(() => {
setCalculatedValue(c => (c += Math.random()));
}, []);
return (
<div>
<ChildA onAction={changeValue} />
<ChildB coreValue={calculatedValue} />
</div>
);
};
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.