将React PureComponent重构为基于钩子的功能组件

时间:2019-03-18 10:05:26

标签: javascript reactjs performance optimization react-hooks

我有一个工作的class based implementation of an Accordion component,我trying to refactor正在使用新的hooks api

我的主要挑战是找到一种方法来仅重新显示已切换的<AccordionSection />,同时防止每次父<AccordionSection/>的状态都重新渲染所有其他<Accordion/>组件(它会跟踪处于其状态的打开部分)。

在基于类的实现中,我设法通过将<AccordionSection />设为PureComponent,并通过更高的顺序将isOpenonClick回调传递给它来实现这一点。组件使用context API,,方法是将这些回调保存在父级<Accordion/>的组件状态中,如下所示:

this.state = {
      /.../
      onClick: this.onClick,
      isOpen: this.isOpen
    };

据我所知,它会保留对它们的引用,从而阻止在每次<Accordion />更新时将它们创建为新实例。

但是,我似乎无法将其与基于钩子的实现一起使用。

我已经尝试不成功的一些事情:

  1. memo包装“手风琴”部分-包括第二个回调参数的各种呈现条件。

  2. onClick包装isOpenuseCallback回调(似乎不起作用,因为它们具有在每个<Accordion/>渲染上更新的依赖项)

  3. onClickisOpen保存到如下状态:const [callbacks] = useState({onClick, isOpen}),然后将callbacks对象作为ContextProvider {{1 }}。 (似乎错了,没用)

以下是对基于工作类的实现的引用:

https://codesandbox.io/s/4pyqoxoz9

和我的钩子重构尝试:

https://codesandbox.io/s/lxp8xz80z7

我将日志保留在value渲染器上,以演示要阻止的重新渲染。

任何输入将不胜感激。

1 个答案:

答案 0 :(得分:2)

所以我在追了太多兔子后最终添加了这个小金块。

const cache = {};

const AccordionSection = memo(({ children, sectionSlug, onClick, isOpen }) => {
  if (cache[sectionSlug]) {
    console.log({
      children: children === cache[sectionSlug].children,
      sectionSlug: sectionSlug === cache[sectionSlug].sectionSlug,
      onClick: onClick === cache[sectionSlug].onClick,
      isOpen: isOpen === cache[sectionSlug].isOpen
    });
  }
  cache[sectionSlug] = { children, sectionSlug, onClick, isOpen };

这表明发生变化的是onClick。当Accordion组件正在渲染并创建一个新的onClick时,这似乎很明显。

onClick包装useCallback,以解决该问题。

const onClick = useCallback(
  sectionSlug =>
    setOpenSections({
      ...(exclusive ? {} : openSections),
      [sectionSlug]: !openSections[sectionSlug]
    }),
  []
);

尽管我似乎确实在破坏exclusive的过程中,因为它现在始终处于启用状态。.

https://codesandbox.io/s/1o08p08m27

哦,我确实在那附近移动了其他一些可能有助于修复的部分。

更新

重构为使用useReducer并将所有逻辑移到那里,以便我们可以提供稳定的onClick

更新

他们说睡眠很好,但对我来说,它只是想入睡。

我知道我想念的东西。.昨晚意识到我们不需要reducer,只需使用setState的函数形式,它就可以使我们从{内访问最新状态。 {1}}备忘的功能。在此处{@ {3}}

转换了@itaydafna的优化