Mic*_*ato 5 frontend memoization reactjs
假设我有一个PersonCard组件,它接收道具,并渲染一张显示人员信息的卡片。
interface PersonProps {
firstName: string,
lastName: string
}
const PersonCard: React.FC<PersonProps> = (firstName, lastName) => {
// render the things
}
Run Code Online (Sandbox Code Playgroud)
现在,如果我要用来React.memo防止该组件不必要的重新渲染,它将如下所示:
const PersonCard: React.FC(<PersonProps>) =>
React.memo(({firstName, lastName}) => {
// render the things
}
)
Run Code Online (Sandbox Code Playgroud)
据我了解,这是可行的:如果我的组件被使用相同的firstNameand调用两次lastName,它就不会重新渲染。
现在,当我们向组合中添加引用类型时,我的问题出现了:
interface PersonProps {
firstName: string,
lastName: string,
hobbies: Array<string>
}
const PersonCard: React.FC(<PersonProps>) =>
React.memo(({firstName, lastName, hobbies}) => {
// render the things
}
)
Run Code Online (Sandbox Code Playgroud)
在这种情况下,React.memo会进行浅比较(作为其默认行为),并且不会对hobbies数组起作用。
因此,即使和不改变,也PersonCard总是会重新渲染,因为它会认为发生了变化:这实际上与根本没有相同。firstNamelastNamehobbieshobbiesReact.memo
所以,我的问题是:我是否错了,或者将任何引用类型作为 prop 传递而不指定深度比较回调完全使 React.memo 的意义无效?
一般来说,您是正确的:假设每个渲染之间的引用发生变化(通常是这种情况),将一个或多个引用类型作为道具传递给记忆组件将阻止记忆。为了唱反调,这里有几个场景,您不希望引用在每次渲染之间发生变化:
如果您将静态引用作为constprop 传递,您可以合理地预期它不会在渲染之间发生变化,并且应该被安全地记住。
const IDS = [1, 2, 3];
const App = () => (
<MyMemoizedComponent ids={IDS} />
);
Run Code Online (Sandbox Code Playgroud)
这也适用于静态let变量,但需要注意的是,如果引用发生变化,记忆组件将重新呈现。
let IDS = [1, 2, 3];
IDS = IDS.slice(); // this would trigger a rerender
Run Code Online (Sandbox Code Playgroud)
在使用有利于引用的组件时,通常会避免静态值。当使用您不希望 的值.current经常更改的 ref 时,您仍然可以获得记忆的好处。
const App = () => {
const idsRef = React.useRef([1, 2, 3]);
return (
<MyMemoizedComponent ids={idsRef.current} />
);
}
Run Code Online (Sandbox Code Playgroud)
React.memo并且React.useMemo并不相互排斥!您可以使用 来记忆一个值,useMemo以防止它破坏记忆。
const App = () => {
const idsMemo = React.useMemo(() => [1, 2, 3], []);
return (
<MyMemoizedComponent ids={idsMemo} />
);
};
Run Code Online (Sandbox Code Playgroud)
这些示例有点人为,但您可以想象这样一个场景:数据未在本地初始化,而是通过网络获取,例如
const App = ({ path }) => {
const ids = React.useMemo(() => fetchFromNetwork(path), [path]);
return (
<MyMemoizedComponent ids={ids} />
);
};
Run Code Online (Sandbox Code Playgroud)
因此,总而言之,将一个或多个引用类型作为道具传递给记忆组件通常会破坏记忆。如果您希望引用类型频繁更改值(~每次渲染一次),只需删除记忆即可,这会导致额外的工作而没有任何好处。如果您不希望它经常更改,请记住它并仅在内部值更改时更新引用(或者,正如您所指出的,为 提供自定义深度相等比较函数React.memo)。
| 归档时间: |
|
| 查看次数: |
2068 次 |
| 最近记录: |