在 React
中 state
一旦发生改变,整个组件都会进行一次 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
是用来缓存值的。
全文完。