We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
useMemo和useCallback相对来说源码比较简单,在函数组件执行到对应的Hook时,同样会将包含该Hook信息的对象链接到Fiber节点的memoizedState属性上的Hooks链表。
useMemo
useCallback
Hook
memoizedState
Hooks
useMemo的Hook对象的memoizedState属性上存的值为计算后的值和依赖数组 —— hook.memoizedState = [nextValue, nextDeps]。
hook.memoizedState = [nextValue, nextDeps]
useCallback的Hook 对象的memoizedState属性上存的值为回调函数和依赖数组 —— hook.memoizedState = [callback, nextDeps]。
hook.memoizedState = [callback, nextDeps]
以下源码浅析React版本为17.0.1。
在React中,Hooks在Mount时和Update时使用的是两个不同函数(useContext除外)。
useContext
Mount时
function mountMemo<T>( nextCreate: () => T, deps: Array<mixed> | void | null, ): T { // 添加到Fiber节点上的Hooks链表 const hook = mountWorkInProgressHook(); const nextDeps = deps === undefined ? null : deps; // 计算需要memo的值 const nextValue = nextCreate(); // hook数据对象上存的值 hook.memoizedState = [nextValue, nextDeps]; return nextValue; }
Update时
function updateMemo<T>( nextCreate: () => T, deps: Array<mixed> | void | null, ): T { // 找到该useMemo对应的hook数据对象 const hook = updateWorkInProgressHook(); const nextDeps = deps === undefined ? null : deps; // 之前存的[nextValue, nextDeps] 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; }
之前有看别人讲useCallback是useMemo的语法糖,现在一看,虽然两个方法完全不同,但也基本完全相同了。
function mountCallback<T>(callback: T, deps: Array<mixed> | void | null): T { // 添加到Fiber节点上的Hooks链表 const hook = mountWorkInProgressHook(); const nextDeps = deps === undefined ? null : deps; // memoizedState存的值是callback hook.memoizedState = [callback, nextDeps]; return callback; }
function updateCallback<T>(callback: T, deps: Array<mixed> | void | null): T { // 找到该useMemo对应的hook数据对象 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; }
这俩方法的源码也太短了,这样就水了一文。
其实一直有一个疑问,如果真的要想让一个函数的地址不发生变化,用useRef来存函数不是更妙吗?
useRef
The text was updated successfully, but these errors were encountered:
从源码看,如果useCallback不存在依赖项useCallback(fn, [])与useCallback(fn)等价吧?
useCallback(fn, [])
useCallback(fn)
Sorry, something went wrong.
@mackxu 并不会等价哦 依赖传入[]的时候,会执行areHookInputsEqual来比较是否相同,相同就返回缓存的函数。 依赖不传入时和没有依赖的useEffect表现相同,每次更新都会执行,因此不会进入判断,每次都会返回最新值。 areHookInputsEqual这个方法会比较数组里的值是否相同。
[]
areHookInputsEqual
useEffect
No branches or pull requests
简述
useMemo
和useCallback
相对来说源码比较简单,在函数组件执行到对应的Hook
时,同样会将包含该Hook
信息的对象链接到Fiber节点的memoizedState
属性上的Hooks
链表。useMemo
的Hook
对象的memoizedState
属性上存的值为计算后的值和依赖数组 ——hook.memoizedState = [nextValue, nextDeps]
。useCallback
的Hook
对象的memoizedState
属性上存的值为回调函数和依赖数组 ——hook.memoizedState = [callback, nextDeps]
。以下源码浅析React版本为17.0.1。
useMemo
在React中,
Hooks
在Mount时和Update时使用的是两个不同函数(useContext
除外)。Mount时
Update时
useCallback
之前有看别人讲
useCallback
是useMemo
的语法糖,现在一看,虽然两个方法完全不同,但也基本完全相同了。Mount时
Update时
这俩方法的源码也太短了,这样就水了一文。
其实一直有一个疑问,如果真的要想让一个函数的地址不发生变化,用
useRef
来存函数不是更妙吗?The text was updated successfully, but these errors were encountered: