如何使 React.memo 重新渲染逻辑在 React 功能组件中具有确定性

时间:2021-07-19 18:54:51

标签: javascript reactjs memoization rerender

我有一个使用 useStateuseContext 的函数式 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);

这成功地阻止了组件重新渲染,因为在树的上一层,MyComponentMyComponentContainer 包裹,它使用自定义钩子 将道具钻入 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 只是在说“不要依赖它来获取功能,因为我们可能会改变它的工作方式?”。

是否有第三方解决方案可以更好地处理此用例?

0 个答案:

没有答案