基础使用:
React组件默认的渲染机制:只要父组件重新渲染子组件就会重新渲染
作用:允许组件在Props没有改变的情况下跳过渲染
说明:经过memo函数包裹生成的缓存组件只有在props发生变化的时候才会重新渲染
备注:只使用memo的场景是只涉及到父传子,如果涉及到子传父那么要使用useCallback进行性能优化
代码如下所示:
import { memo, useState } from 'react';
// memo进行缓存, 只要props发生变化的时候才会重新渲染(没有考虑context)
const MemoSon = memo(function Son() {
console.log('我是子组件,我重新渲染了');
return <div>Son</div>;
})
function Layout() {
const [count, setCount] = useState(0);
return (
<div>
<button onClick={() => setCount(count + 1)}>count: {count}</button>
<MemoSon />
</div>
)
}
export default Layout;
React.memo - props的比较机制
机制:在使用memo缓存组件之后, React会对每一个prop使用Object.is比较新值和老值,返回true,表示没有变化
prop是简单类型(基本数据类型)
Object.is(3, 3) ==> true 没有变化
prop是引用数据类型(对象/数组)
Object([], []) => false 有变化,React只关心引用是否变化
代码如下:
1. 基本数据类型演示:
import { memo, useState } from 'react';
// 1. 传递一个简单类型prop prop变化时组件重新渲染
const MemoSon = memo(function Son({count}) {
console.log('我是子组件,我重新渲染了');
return <div>Son --- {count}</div>;
})
function Layout() {
const [count, setCount] = useState(0);
const num = 100;
return (
<div>
{/* 点击时prop发生变化,所以会触发Son重新渲染 */}
<button onClick={() => setCount(count + 1)}>count: {count}</button>
{/* 使用count时,点击时prop发生变化,所以会触发Son重新渲染, 使用num时,prop没发生变化不会重新渲染 */}
<MemoSon count={count} />
</div>
)
}
export default Layout;
2. 引用数据类型演示
import { memo, useState } from 'react';
// 当父组件的函数重新执行时,实际上形成的是新的数组引用,所以重新渲染了
const MemoSon = memo(function Son({ list }) {
console.log('我是子组件,我重新渲染了');
return <div>Son --- {list}</div>;
})
function Layout() {
const [count, setCount] = useState(0);
const list = [1, 3, 5];
return (
<div>
{/* 点击时虽然prop没变化,但由于当父组件的函数重新执行时,实际上形成的是新的数组引用,所以重新渲染了 */}
<button onClick={() => setCount(count + 1)}>count: {count}</button>
<MemoSon list={list} />
</div>
)
}
export default Layout;
3. 如果非要使用引用数据类型,也可以使用useMemo性能优化,代码如下:
import { memo, useMemo, useState } from 'react';
// 保证引用稳定 -> useMemo 组件渲染的过程中缓存一个值
const MemoSon = memo(function Son({ list }) {
console.log('我是子组件,我重新渲染了');
return <div>Son --- {list}</div>;
})
function Layout() {
const [count, setCount] = useState(0);
const list = useMemo(() => {
return [1, 3, 5]
}, [])
return (
<div>
{/* 点击时虽然prop没变化,但由于当父组件的函数重新执行时,实际上形成的是新的数组引用,所以重新渲染了 */}
<button onClick={() => setCount(count + 1)}>count: {count}</button>
<MemoSon list={list} />
</div>
)
}
export default Layout;