【问题标题】:React.useMemo does not work to prevent re-rendersReact.useMemo 不能防止重新渲染
【发布时间】:2019-10-22 01:58:26
【问题描述】:

我有以下简单的组件:

const Dashboard = () => {
  const [{ data, loading, hasError, errors }] = useApiCall(true)

  if (hasError) {
    return null
  }

  return (
    <Fragment>
      <ActivityFeedTitle>
      <ActivityFeed data={data} isLoading={loading} />
    </Fragment>
  )
}

export default Dashboard

我想阻止 ActivityFeedTitle 组件的所有重新渲染,以便它在加载时只渲染一次。我的理解是我应该能够使用带有空依赖项数组的React.useMemo 钩子来实现这一点。我把return改成了:

return (
    <Fragment>
        {React.useMemo(() => <ActivityFeedTitle>, [])}
        <ActivityFeed data={data} isLoading={loading} />
    </Fragment>
)

就我而言,这应该防止该组件的所有重新渲染?但是,ActivityFeedTitle 组件仍会在每次渲染 Dashboard 组件时重新渲染。

我错过了什么?

编辑:

使用React.memo 仍然会导致同样的问题。我尝试按如下方式记忆我的ActivityFeedTitle 组件:

const Memo = React.memo(() => (
  <ActivityFeedTitle />
))

然后在我的回报中这样使用它:

return (
    <Fragment>
        {<Memo />}
        <ActivityFeed data={data} isLoading={loading} />
    </Fragment>
)

出现同样的问题。我还尝试将() =&gt; false 作为React.memo 的第二个参数传入,但这也没有用。

【问题讨论】:

    标签: javascript reactjs typescript react-hooks


    【解决方案1】:

    使用 React.memo() 代替基于 props 的记忆组件。

    React.memo(function ActivityFeedTitle(props) {
      return <span>{props.title}</span>
    })
    

    注意:

    此方法仅作为性能优化存在。不要依赖它来“阻止”渲染,因为这可能会导致错误。

    【讨论】:

    • 您好,谢谢您的回答。我也试过用React.memo 解决这个问题,但我遇到了同样的问题。请参阅我对 OP 的最新编辑。是不是因为我的组件没有道具?
    • ActivityFeed 是一个函数组件,FC 有没有其他解决方法?
    • @JavascriptLoser 那么你是如何验证它没有被优化的呢?查看更新的答案。
    【解决方案2】:

    传递给React.memo 的第二个参数需要返回true 以防止重新渲染。它不是计算组件是否应该更新,而是确定传递的 props 是否相等。

    【讨论】:

      【解决方案3】:

      您对useMemo 的使用不正确。

      来自 react hooks 文档:

      传递一个“create”函数和一个依赖数组。 useMemo 将 仅当依赖项之一具有时才重新计算记忆值 改变了。这种优化有助于避免昂贵的计算 每次渲染。

      如果没有提供数组,每次渲染都会计算一个新值。

      您需要在这里使用useMemouseEffect 一样计算值,而不是渲染组件。

      React.memo

      React.memo() 是您正在寻找的那个。除非道具发生变化,否则它会防止重新渲染。

      【讨论】:

      • 您好,谢谢您的回答。我也试过用React.memo 解决这个问题,但我遇到了同样的问题。查看我对 OP 的最新编辑。
      【解决方案4】:

      您可以使用 React.memo 并在定义组件的地方使用它,而不是在创建组件实例的地方,您可以在 ActivityFeedTitle 组件中这样做

      const ActivityFeedTitle = React.memo(() => {
        return (
         //your return
        )
      })
      

      希望对你有帮助

      【讨论】:

        【解决方案5】:

        这是因为渲染父级会导致其子级在大多数情况下重新渲染。此处更好的优化是将您的数据获取逻辑放置在 ActivityFeed 组件中或放入您包装 ActivityFeed 的 HOC 中。

        【讨论】:

          猜你喜欢
          • 2020-07-25
          • 1970-01-01
          • 2021-02-14
          • 1970-01-01
          • 2020-03-27
          • 2023-03-02
          • 2021-01-07
          • 2016-07-26
          • 2017-11-21
          相关资源
          最近更新 更多