本节课我们来实现一下useEffect中的cleanUp,它会再调用useEffect之前调用,目的是清空所有副作用,当deps为空的时候不会调用cleanUp。
app.js
React.useEffect(() => {
console.log('init')
return () => {
console.log("cleanup 0")
}
}, [])
React.useEffect(() => {
console.log('update1', count)
return () => {
console.log("cleanup 1")
}
}, [count])
React.useEffect(() => {
console.log('update2', count)
return () => {
console.log("cleanup 2")
}
}, [count])
cleanUp的存放,以及调用
- react.js
function commitEffectHooks() {
function run(fiber) {
if (!fiber) {
return
}
if(!fiber.alternate) {
fiber?.effectHooks?.forEach((hook) => {
hook.cleanup = hook.callback()
})
}else {
// update
// deps 有没有发生改变
fiber.effectHooks?.forEach((newHook, index)=> {
if(newHook.deps.length> 0 ) {
const oldEffectHook = fiber.alternate?.effectHooks[index]
// some
const needUpdate = oldEffectHook?.deps.some((oldDep, i) => {
return oldDep !== newHook.deps[i]
})
needUpdate && (newHook.cleanup = newHook.callback())
}
})
}
run(fiber.child)
run(fiber.sibling)
}
function runCleanup (fiber) {
if(!fiber) return
fiber.alternate?.effectHooks?.forEach((hook) => {
hook.cleanup && hook.cleanup()
})
runCleanup(fiber.child)
runCleanup(fiber.sibling)
}
runCleanup(wipRoot)
run(wipFiber)
}
处理依赖为空的情况
function runCleanup (fiber) {
if(!fiber) return
fiber.alternate?.effectHooks?.forEach((hook) => {
if(hook.deps.length > 0) {
hook.cleanup && hook.cleanup()
}
})
runCleanup(fiber.child)
runCleanup(fiber.sibling)
}