- React.memo:依赖的 props 变化,子组件重新 render (
浅比较 )
- useMemo:缓存一个值,依赖更新( 对照vue中的
computed )
- useCallback:缓存一个函数,依赖更新( 对照vue中的
watch )
1、useMemo & memo
import React, { useMemo, useState } from 'react';
import Son from './Son';
const MemoCallBack = () => {
const [count, setCount] = useState(0);
const [sex, setSex] = useState('男');
const arr = [
{ sex, age: 12 },
{ sex: '女', age: 18 },
{ sex: '男', age: 6 }
];
const [arr, setArr] = useState([
{ sex, age: 12 },
{ sex: '女', age: 18 },
{ sex: '男', age: 6 }
]);
const arr = useMemo(() => {
return [
{ sex, age: 12 },
{ sex: '女', age: 18 },
{ sex: '男', age: 6 }
];
}, [sex]);
return (
<div>
<button onClick={() => {
setCount(count + 1);
}}>改变count</button>
<button onClick={
() => {
setSex(sex === '男' ? '女' : '男');
}}>改变性别</button>
<button onClick={() => {
setArr([...arr, { sex: '男', age: Date.now() }]);
}}>新增人员</button>
{/* 子组件 */}
<Son arr={arr} />
</div>
);
};
export default MemoCallBack;
import React, {useEffect, memo} from 'react'
const Son = ({arr}) => {
console.log('是否触发了子组件更新', arr)
return (
<>
{arr.map(item => (
<div key={item.age}>
<span>性别:{item.sex} - </span>
<span>年龄:{item.age}</span>
</div>
))}
</>
)
}
export default memo(Son)
2、useCallback
import React, {useMemo, useState} from 'react'
import Son from './Son'
const MemoCallBack = () => {
const [count, setCount] = useState(0)
const [sex, setSex] = useState('男')
const changeCount1 = () => {
setCount(count + 1);
};
const changeCount2 = useCallback(() => {
setCount(count + 1);
}, [sex]);
return (
<div>
{/* 子组件 */}
<Son {...{ changeCount1, changeCount2 }} />
</div>
);
}
export default MemoCallBack
import React, {useEffect} from 'react'
const Son = ({changeCount1,changeCount2}) => {
console.log('是否触发了子组件更新', )
return (
<>
<button onClick={changeCount1}>改变count</button>
<button onClick={changeCount2}>改变Sex</button>
</>
)
}
export default Son
3、useMemo 源码
function mountMemo<T>(
nextCreate: () => T,
deps: Array<mixed> | void | null,
): T {
const hook = mountWorkInProgressHook();
const nextDeps = deps === undefined ? null : deps;
const nextValue = nextCreate();
hook.memoizedState = [nextValue, nextDeps];
return nextValue;
}
function updateMemo<T>(
nextCreate: () => T,
deps: Array<mixed> | void | null,
): T {
const hook = updateWorkInProgressHook();
const nextDeps = deps === undefined ? null : deps;
const prevState = hook.memoizedState;
if (prevState !== null) {
if (nextDeps !== null) {
const prevDeps: Array<mixed> | null = prevState[1];
if (areHookInputsEqual(nextDeps, prevDeps)) {
return prevState[0];
}
}
}
const nextValue = nextCreate();
hook.memoizedState = [nextValue, nextDeps];
return nextValue;
}
4、useCallback 源码
function mountCallback<T>(callback: T, deps: Array<mixed> | void | null): T {
const hook = mountWorkInProgressHook();
const nextDeps = deps === undefined ? null : deps;
hook.memoizedState = [callback, nextDeps];
return callback;
}
function updateCallback<T>(callback: T, deps: Array<mixed> | void | null): T {
const hook = updateWorkInProgressHook();
const nextDeps = deps === undefined ? null : deps;
const prevState = hook.memoizedState;
if (prevState !== null) {
if (nextDeps !== null) {
const prevDeps: Array<mixed> | null = prevState[1];
if (areHookInputsEqual(nextDeps, prevDeps)) {
return prevState[0];
}
}
}
hook.memoizedState = [callback, nextDeps];
return callback;
}