在 React 应用程序分析中使用备忘录重新渲染子项
in React app profiling child re-rendering with memo
在分析结果中,组件 (Table
) 使用 React.memo
并且显示没有重新渲染
但下面显示了相同的 Table
组件,并且在 Why did this render 中提到父级重新渲染
Table
以这种方式使用备忘录,querystring
保持不变。
function areEqal(prevTable, nextTable) {
return prevTable.queryString === nextTable.queryString;
}
const MemoTable = memo(Table, areEqal);
...
<MemoTable queryString={queryString} />
问题是,为什么 Table
显示两次(一次没有重新渲染,然后是)以及为什么在 querystring
更改时重新渲染。
memo
只能阻止与道具相关的渲染。如果您订阅的上下文值发生变化,渲染可能仍会发生。正如评论中所讨论的,您显然使用了几个上下文,而这些正是导致渲染的原因。
虽然删除 useContext
s 似乎对您的情况有效,但您没有预料到此重新呈现的事实可能表明 DataContext.provider 有一个 common mistake 其中您正在更改每个渲染器的上下文值。如果您要提供一个对象,则需要确保仅在对象的属性实际发生变化时才创建一个新对象。例如,如果您当前的代码是这样的:
const Example = ({ children }) => {
const [userPreferences, setUserPreferences] = useState('something');
return (
<DataContext.Provider value={{ userPreferences, setUserPreferences }}>
{children}
</DataContext.Provider>
);
}
...那么你应该像这样记住这个值:
const Example = ({ children }) => {
const [userPreferences, setUserPreferences] = useState('something');
const value = useMemo(() => {
return { userPreferences, setUserPreferences }
}, [userPreferences]);
return (
<DataContext.Provider value={value}>
{children}
</DataContext.Provider>
);
}
至于开发工具中的两份Table
,第一份是memoized组件MemoTable。 MemoTable 然后在其中呈现一个未记忆的 Table,这是第二个。 “Table (memo)”是 memo
给组件的默认名称 returns。如果您想更改该名称以使其在开发工具中显示不同,您可以:
const MemoTable = memo(Table, areEqal);
MemoTable.displayName = "Hello world";
在分析结果中,组件 (Table
) 使用 React.memo
并且显示没有重新渲染
但下面显示了相同的 Table
组件,并且在 Why did this render 中提到父级重新渲染
Table
以这种方式使用备忘录,querystring
保持不变。
function areEqal(prevTable, nextTable) {
return prevTable.queryString === nextTable.queryString;
}
const MemoTable = memo(Table, areEqal);
...
<MemoTable queryString={queryString} />
问题是,为什么 Table
显示两次(一次没有重新渲染,然后是)以及为什么在 querystring
更改时重新渲染。
memo
只能阻止与道具相关的渲染。如果您订阅的上下文值发生变化,渲染可能仍会发生。正如评论中所讨论的,您显然使用了几个上下文,而这些正是导致渲染的原因。
虽然删除 useContext
s 似乎对您的情况有效,但您没有预料到此重新呈现的事实可能表明 DataContext.provider 有一个 common mistake 其中您正在更改每个渲染器的上下文值。如果您要提供一个对象,则需要确保仅在对象的属性实际发生变化时才创建一个新对象。例如,如果您当前的代码是这样的:
const Example = ({ children }) => {
const [userPreferences, setUserPreferences] = useState('something');
return (
<DataContext.Provider value={{ userPreferences, setUserPreferences }}>
{children}
</DataContext.Provider>
);
}
...那么你应该像这样记住这个值:
const Example = ({ children }) => {
const [userPreferences, setUserPreferences] = useState('something');
const value = useMemo(() => {
return { userPreferences, setUserPreferences }
}, [userPreferences]);
return (
<DataContext.Provider value={value}>
{children}
</DataContext.Provider>
);
}
至于开发工具中的两份Table
,第一份是memoized组件MemoTable。 MemoTable 然后在其中呈现一个未记忆的 Table,这是第二个。 “Table (memo)”是 memo
给组件的默认名称 returns。如果您想更改该名称以使其在开发工具中显示不同,您可以:
const MemoTable = memo(Table, areEqal);
MemoTable.displayName = "Hello world";