Optimizing re-render in react context confuses me. It actually prevents its context subscriber from re-rendering?

huangapple go评论74阅读模式
英文:

Optimizing re-render in react context confuses me. It actually prevents its context subscriber from re-rendering?

问题

根据React文档useMemouseCallback 有助于性能优化,因为渲染之间的比较工作得很正确。

然而,根据我的理解,每当父组件重新渲染时,其子组件也会重新渲染。由于React上下文与提供者一起工作,所有上下文订阅者都在父提供者之下。因此,父提供者的重新渲染可能也会导致子组件重新渲染。

React文档中下面的陈述让我感到困惑。有人能解释一下吗?

即使 MyApp 需要重新渲染,调用 useContext(AuthContext) 的组件也不需要重新渲染。

英文:

According to React doc, useMemo and useCallback help performant optimization because comparison between rendering works correctly.

In my understanding, however, whenever parent component re-renders, its child components also re-render. Since react context works with the provider, all context subscribers are under parent provider. So parent provider re-rendering probably causes child re-rendering as well.

The statement below of React doc confuses me. Anyone can explain this?

> even if MyApp needs to re-render, the components calling useContext(AuthContext) won’t need to re-render

答案1

得分: 1

在我的理解中,每当父组件重新渲染时,它的子组件也会重新渲染。

默认情况下是如此,但React.memo可以用于跳过子组件的重新渲染,如果它们的属性没有更改。因此,如果您使用React.memo来提高性能,您需要确保上下文值不会一直变化,这将消除React.memo的性能优势。

例如,您提供的文档中,MyApp 返回如下内容:

const MyApp = () => {
  // ...
  return (
    <AuthContext.Provider value={contextValue}>
      <Page />
    </AuthContext.Provider>
  );
}

假设Page 实现如下:

import { memo } from 'react';

const Page = memo(() => {
  return (
    <ChildThatUsesContext />
  )
})

const ChildThatUsesContext = () => {
  const value = useContext(AuthContext);

  // ... 做一些操作
}

如果MyApp 重新渲染,而contextValue 没有更改,那么PageChildThatUsesContext 都可以跳过渲染。

如果MyApp 重新渲染,而contextValue 确实 更改,那么Page 将能够跳过渲染,但ChildThatUsesContext(及其所有后代)将不得不重新渲染,因为它调用了useContext(AuthContext);

因此,将contextValue 进行记忆化的原因是为了更频繁地让我们进入第一种情况,即所有组件都跳过重新渲染,而不仅仅是Page

英文:

> In my understanding, however, whenever parent component re-renders, its child components also re-render.

That's true by default, but React.memo can be used to skip rerendering of a child if its props have not changed. So if you're using React.memo to improve performance, you need to make sure your context value isn't changing all the time, which would eliminate the gains from React.memo

For example, the documentation you linked has MyApp returning the following:

const MyApp = () =&gt; {
  // ...
  return (
    &lt;AuthContext.Provider value={contextValue}&gt;
      &lt;Page /&gt;
    &lt;/AuthContext.Provider&gt;
  );
}

Suppose that Page is implemented something like this:

import { memo } from &#39;react&#39;;

const Page = memo(() =&gt; {
  return (
    &lt;ChildThatUsesContext /&gt;
  )
})

const ChildThatUsesContext = () =&gt; {
  const value = useContext(AuthContext);

  // ... do stuff
}

If MyApp rerenders and the contextValue does not change, then both Page and ChildThatUsesContext can skip rendering.

If MyApp rerenders and the contextValue does change, then Page will be able to skip rendering, but ChildThatUsesContext (and all its descendants) will have to render because it called useContext(AuthContext);

So the reason to memoize contextValue is to put us in that first case more often, with all of the components skipping rendering, not just Page.

huangapple
  • 本文由 发表于 2023年3月31日 23:08:34
  • 转载请务必保留本文链接:https://go.coder-hub.com/75900071.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定