Reactstate 一旦发生改变,整个组件都会进行一次 re-render,包括子组件。这里的 re-render 过程并不是真的重新渲染,而是首先进行 dom diff 找到前后节点快照的差异点,然后只做最小的更新,利用js计算代替昂贵的 dom 操作。

不要过早的进行优化,React本身就是高性能的View层解决方案

useMemo 与 react memo 的区别?

React memo包裹一个组件,避免组件重复渲染。

useMemo VS useCallback?

  • useMemo 作用于缓存值
  • useCallback 作用于缓存函数

举个例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
import React from 'react';

const users = [
{ id: 'a', name: 'Robin' },
{ id: 'b', name: 'Dennis' },
];

const App = () => {
const [text, setText] = React.useState('');
const [search, setSearch] = React.useState('');

const handleText = (event) => {
setText(event.target.value);
};

const handleSearch = () => {
setSearch(text);
};

const filteredUsers = users.filter((user) => {
return user.name.toLowerCase().includes(search.toLowerCase());
});

return (
<div>
<input type="text" value={text} onChange={handleText} />
<button type="button" onClick={handleSearch}>
Search
</button>

<List list={filteredUsers} />
</div>
);
};

const List = ({ list }) => {
return (
<ul>
{list.map((item) => (
<ListItem key={item.id} item={item} />
))}
</ul>
);
};

const ListItem = ({ item }) => {
return <li>{item.name}</li>;
};

export default App;
1
2
3
4
5
6
7
8
9
10
function App() {
...

const filteredUsers = users.filter((user) => {
console.log('Filter function is running ...');
return user.name.toLowerCase().includes(search.toLowerCase());
});

...
}

项目简单且数据量不大的时候,这点性能开销可能感觉不到什么影响。只有列表数据足够大的时候,每次键盘的输入都会执行 filter 回调,这会明显降低应用的性能。

这时 useMemo 就派上用场了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function App() {
...

const filteredUsers = React.useMemo(
() =>
users.filter((user) => {
console.log('Filter function is running ...');
return user.name.toLowerCase().includes(search.toLowerCase());
}),
[search]
);

...
}

search 改变的时候才会执行 users.filter 回调函数,其他时候都不会触发执行。

为什么React不把useMemo作为默认行为?

useMemo 每次重新渲染时会根据依赖项数组中的依赖项,来决定是否应该重新计算值。这种计算比重新计算值要昂贵得多,所以 useMemo 是用来缓存值的。