英文:
Optimizing re-render in react context confuses me. It actually prevents its context subscriber from re-rendering?
问题
根据React文档,useMemo
和 useCallback
有助于性能优化,因为渲染之间的比较工作得很正确。
然而,根据我的理解,每当父组件重新渲染时,其子组件也会重新渲染。由于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
没有更改,那么Page
和ChildThatUsesContext
都可以跳过渲染。
如果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 = () => {
// ...
return (
<AuthContext.Provider value={contextValue}>
<Page />
</AuthContext.Provider>
);
}
Suppose that Page
is implemented something like this:
import { memo } from 'react';
const Page = memo(() => {
return (
<ChildThatUsesContext />
)
})
const ChildThatUsesContext = () => {
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
.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论