
通过结果可以得到,先执行 useMemo,接着执行 useLayoutEffect 的 side effect cleanup,useEffect 的 side effect cleanup,等到 React update DOM and Refs 执行后,再执行 useLayoutEffect、useEffect。
通过这个例子,基本上弄清楚 useEffect 的执行顺序,由此分析使用 useEffect 模拟生命周期方法不当会导致什么问题。
- 对于生命周期挂载方法,使用
useEffect模拟mount如下:useEffect(() => { // do something }, []);只有当
useEffect的 deps 参数是空数组时,该用法才等同于mount方法 - 对于组件销毁的生命周期方法,使用
useEffect模拟unmount如下:useEffect(() => { return () => { // do something } }, []);
useMount 和 useUnmount
前面的问题根本原因是 useEffect 与 Lifecycle Methods 需要解耦。如果 useEffect 的 deps 参数不是空数组,那么当前的 useEffect 不等同 mount 方法,就会造成意外的结果
社区里提供专门的 ahooks 解决这个问题,这个第三方库中有两个重要方法,分别是 useMount 和 useUnmount
useMount 的实现如下:
// useMount.ts
import { useEffect } from 'react'
const useMount = (fn: () => void) => {
if (!isFunction(fn)) {
console.error(`useMount: parameter `fn` expected to be a function, but got "${typeof fn}".`)
}
useEffect(() => {
fn?.()
}, [])
}
export default useMount
useUnmount 的实现如下:
// useUnMount.ts
import { useEffect, useRef } from 'react'
export default function useUnmount(fn: () => void): void {
if (!isFunction(fn)) {
console.error(`useUnmount: parameter `fn` expected to be a function, but got "${typeof fn}".`)
}
const ref = useRef(fn)
useEffect(
(): (() => void) => (): void => {
ref.current?.()
},
[]
)
}
function isFunction(fn: unknown): fn is Function {
return typeof fn === 'function'
}
在项目中这样使用useMount和useUnMount:
const App = () => {
useMount(() => {
// ...
})
useUnMount(() => {
// ...
})
return <></>
}
使用useMount和useUnmount就不用考虑传入的依赖,实现useEffect与 Lifecycle Methods 解耦
以上就是关于我们为什么需要 useMount 和 useUnmount 的详细内容,更多请关注www.mimiwuqi.com的其它相关文章!