Appearance
useMemo
作用
返回一个 memoized 值。
把“创建”函数和依赖项数组作为参数传入 useMemo
,它仅会在某个依赖项改变时才重新计算 memoized 值。这种优化有助于避免在每次渲染时都进行高开销的计算。
栗子
js
const App = props => {
// 添加一个 hook
const [num, setNum] = React.useState(1)
const [visible, setVisible] = React.useState(true)
const handleClickBtn = () => {
setNum(num2 => num2 + 2)
}
// 切换visible
const handleClickChangeVisible = () => {
setNum(!visible)
}
// 打印
const result= React.useCallback(() => {
console.log("result = " + num)
}, [visible])
return (
<div>
<button onClick={handleClickBtn}>切换Num = {num}</button>
<button onClick={handleClickChangeVisible}>切换Visible = {visible}</button>
<button >{result} </button>
</div>
)
}
点击切换num ;num得值在不断的增加;但是这时候如果不点击 切换Visible ;result的值永远是 useCallback1。
源码分析
仍然分成两个部分: 初次渲染 和 更新渲染 。此处我们一起讲解
js
/**
* useMemo 在初次渲染执行方法
* @param {*} nextCreate
* @param {*} deps
* @returns
*/
function mountMemo<T>(
nextCreate: () => T,
deps: Array<mixed> | void | null,
): T {
// 创建 hook
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 {
// 找到对应的 hook
const hook = updateWorkInProgressHook();
const nextDeps = deps === undefined ? null : deps;
const prevState = hook.memoizedState;
if (prevState !== null) {
// Assume these are defined. If they're not, areHookInputsEqual will warn.
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;
}
其跟useCallback 很像,都将信息以hook的形式保存在 FiberNode.memoizedState上。
如何只有deps更新的时候才会生再次执行func生成新的value ?
这就是在updateMemo中实现的,其先获取原来的hook,然后通过areHookInputsEqual(nextDeps, prevDeps)
判断新旧hook的deps是够发生更新,如果发生更新就执行nextCreate()返回新的 value ;否则返回旧的prevState[0]。