【问题标题】:React component works fine, but attempting to use useMemo() results in an errorReact 组件工作正常,但尝试使用 useMemo() 会导致错误
【发布时间】:2021-04-16 20:41:33
【问题描述】:

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

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

这很好用。

正如 React 用户所知道的,当任何输入发生变化时,React 都会重新呈现表单。由于日历仅依赖于某些输入(fullNameemailonEventScheduled),而不依赖于其他输入,并且绘制速度很慢,我想使用 useMemo() 来停止日历重新渲染:

(根据@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()

值得一提的是,如果一个组件接收到一个函数作为 props,你需要使用 useCallback 钩子,以便它只在必要时再次声明该函数。否则每次渲染时 props 都会不同,因为函数 prop 总是有一个新的引用。

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

这修复了错误,但在 emailfullNameonEventScheduled 之外的项目被修改时仍会不必要地重新渲染。

如何记忆这个钩子组件?

【问题讨论】:

  • Calendar 是一个 React 组件,而不是一个简单的类。您需要在 useMemo 中使用 JSX 语法才能使其工作:return &lt;Calendar fullName={fullName} email={email} onEventScheduled={onEventScheduled} /&gt;
  • 您还需要将 memoized 值用作已渲染的组件,而不是要渲染的组件。这样做:const memoizedCalendar = useMemo(...) 然后在你的 JSX 中 {memoizedCalendar}
  • 在下面添加了答案

标签: javascript reactjs react-hooks react-usememo


【解决方案1】:

要使用 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>
);

【讨论】:

    猜你喜欢
    • 2016-08-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-13
    • 1970-01-01
    • 2014-03-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多