Hooks模拟constructor
constructor(){
super()
this.state={count:0}
}
//Hooks模拟constructor
const [count setCount]=useState(0)
Hooks模拟componentDidMount
componentDidMount(){
console.log('I am mounted')
}
//Hooks模拟componentDidMount
useEffect(()=>console.log('mounted'),[])
useEffect拥有两个参数,第一个参数作为回调函数会在浏览器布局和绘制完成后调用,因此它不会阻碍浏览器的渲染进程,第二个参数是一个数组,也是依赖项
1、当依赖列表存在并有值,如果列表中的任何值发生更改,则每次渲染后都会触发回调
2、当它不存在时,每次渲染后都会触发回调
3、当它是一个空列表时,回调只会被触发一次,类似于componentDidMount
模拟shouldComponentUpdate
shouldComponentUpdate(nextProps,nextState){
console.log('shouldComponentUpdate')
return true //更新组件 反之不更新
}
// React.memo包裹一个组件来对它的props进行浅比较,但这不是一个hooks,因为它的写法和hooks不同,其实React.memo等效于PureComponent,但它只比较props
// 模拟shouldComponentUpdate
const MyComponent=React.memo(
_MyComponent,
(prevProps,nextProps)=>nextProps.count!==preProps.count
)
Hooks模拟componentDidUpdate
componentDidMount() {console.log('mounted or updated');}
componentDidUpate(){console.log('mounted or updated')}
//Hooks模拟componentDidUpdate
useEffect(()=>console.log('mounted or updated'))
//这里的回调函数会在每次渲染后调用,因此不仅可以访问componentDidUpdate,还可以访问componentDidMount,如果只想模拟componentDidUpdate,我们可以这样来实现
const mounted=useRef()
useEffect(()=>{
if(!mounted.current){mounted.current=true}else{console.log('I am didUpdate')}
})
//useRef在组件中创建“实例变量”,它作为一个标志来指示组件是否处于挂载或更新阶段。当组件更新完成后在会执行else里面的内容,以此来单独模拟componentDidUpdate
Hooks模拟componentWillUnmount
componentWillUnmount(){
console.log('will unmount')
}
//hooks
useEffect(()=>{
//此处并不同于willUnMount porps发生变化即更新,也会执行结束监听
//准确的说:返回的函数会在下一次effect执行之前,被执行
return ()=>{console.log('will unmount')}
},[])
//当在useEffect的回调函数中返回一个函数时,这个函数会在组件卸载前被调用。我们可以在这里清除定时器或事件监听器。
模拟的生命周期和class中的生命周期有什么区别吗? useEffect中return执行时机
https://codesandbox.io/s/useeffect-clean-forked-xq56bg
1、默认的useEffect(不带[]或者监听的[count有变化])中return的清理函数,它和componentWillUnmount有本质区别的,默认情况下return,在每次useEffect执行前都会执行,并不是只有组件卸载的时候执行。每次执行前会拿到上次的值,如果是空数组则在组件销毁时执行
2、useEffect在副作用结束之后,会延迟一段时间执行,并非同步执行,和compontDidMount有本质区别。遇到dom操作,最好使用useLayoutEffect。
hooks 模拟的生命周期与class中的生命周期不尽相同,我们在使用时,还是需要思考业务场景下那种方式最适合。