React 组件工作正常,但尝试使用 useMemo() 会导致错误

React component works fine, but attempting to use useMemo() results in an error

我有一张表格,里面有会议预订。其中一部分是日历组件,它具有相当复杂的 UI.

<Calendar fullName={fullName} email={email} onEventScheduled={onEventScheduled} />

这很好用。

正如 React 用户所知,当任何输入发生变化时,都会对表单做出反应 re-renders。由于日历仅依赖于某些输入(fullNameemailonEventScheduled),而不依赖于其他输入,而且绘制速度很慢,所以我想使用 useMemo() 停止日历 re-rendering:

(根据@dmitryguzeev 评论更新为使用 JSX)

  const MemoizedCalendar = useMemo(() => {
    return <Calendar fullName={fullName} email={email} onEventScheduled={onEventScheduled} />;
  }, [email, fullName, onEventScheduled]);

然后稍后

<MemoizedCalendar fullName={fullName} email={email} onEventScheduled={onEventScheduled} />

但是切换到 MemoizedCalendar 会出现以下错误:

Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: object.

Check the render method of `Formik`.

(我碰巧在使用 Formik,但是该组件在上面的 Calendar 下工作正常,只是 MemoizedCalendar 失败了)

编辑:我也在reading this article on UseMemo()

之后尝试了useCallback()

It is worth saying that if a component receives a function as a prop, you need to use the useCallback hook, so that it only declares the function again when necessary. Otherwise props will be different every render, since the function prop will always have a new reference.

const MemoizedCalendar = useCallback(() => {
    return Calendar(email, fullName, onEventScheduled);
  }, [email, fullName, onEventScheduled]);

修复了错误,但当 emailfullNameonEventScheduled 之外的项目被修改时,仍然 re-renders 不必要。

如何记忆这个钩子组件?

要使用 useMemo 记住您的组件 JSX 树部分,您需要先在 useMemo 中单独渲染它:

// I usually prefix the name of this variable with rendered* so
// that the user below knows how to use it properly
const renderedCalendar = useMemo(() => {
  // This code below tells react to render Calendar with given props.
  // This JSX will be transformed into a function call and it will
  // happen only after the dependency array given to useMemo changes.
  return <Calendar fullName={fullName} email={email} onEventScheduled={onEventScheduled} />
}, [fullName, email, onEventScheduled]);

然后将其用作 JSX 树中的值而不是组件:

return (
  <div>
    ...
    {renderedCalendar}
  </div>
);