我有一个使用 useState
和 useContext
的函数式 React 组件,它从上下文和道具派生其显示属性。
我使用 useMemo
和它的第二个参数 areEqual
函数来防止组件在新道具进来时重新渲染。 prop 有几十个值,但我只想在 prop 更改为特定值时重新渲染组件。
这是一个简化的例子:
const MyComponent = (props) => {
const {contextThing} = useContext();
const {stateThing} = useState();
const {propsThing} = props;
// Since only foo changes what is rendered, I want to prevent rerendering unless the
// prop changes to 'foo'
const derivedThing =
(propsThing === 'foo' && contextThing === 'bar') ?
'foobar' :
null;
return (
<>
<div>{contextThing}</div>
<div>{stateThing}</div>
<div>{propsThing}</div>
<div>{derivedThing}</div>
<>
}
function preventRerender(prevProps, nextProps) {
if(prevProps.propsThing !== 'foo' }} nextProps.propsThing !== 'foo') {
return true;
}
return false;
}
export default memo(MyComponent, preventRerender);
这成功地阻止了组件重新渲染,因为在树的上一层,MyComponent
被 MyComponentContainer
包裹,它使用自定义钩子
将道具钻入 MyComponent
,如下所示:
const MyComponentContainer = () {
// Note: `useMyCustomHook` uses `useContext`, `useReducer` and `useState`
const { propsThing } = useMyCustomHook();
return (
<>
<Header />
<MyComponent propsThing={propsThing} />
<Footer />
<>
);
}
export default MyComponentContainer;
参考 areEqual
函数:
此方法仅作为性能优化存在。不要依赖它来“阻止”渲染,因为这可能会导致错误。
https://reactjs.org/docs/react-api.html#reactmemo
React 文档似乎说这是一种不好的做法。我基本上将 memo
/areEqual
视为类组件中的 shouldComponentUpdate
。
我无法控制 propsThing
何时更改。它由用户操作和发布/订阅到 3rd 方 API 驱动。
这是我需要用不同模式替换的反模式吗?
或者 React 只是在说“不要依赖它来获取功能,因为我们可能会改变它的工作方式?”。
是否有第三方解决方案可以更好地处理此用例?