类组件
类组件中定义了几组常用的生命周期的hook,分别为这几个函数打log来查看它们的调用时机
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| class ClassComponent extends React.Component {
componentDidMount(): void { console.log('class component did mount') }
componentWillUnmount(): void { console.log('class component will unmount') }
componentDidUpdate(prevProps: Readonly<ModelProps>, prevState: Readonly<{}>, snapshot?: any): void { console.log('class component did update') } render(): React.ReactNode { console.log('class component render') return ( <View style={styles.container}> <Text style={styles.title}>{`Class Component` }</Text> </View> ) } }
|
当首次渲染ClassComponent时的log
1 2 3
| LOG father render LOG class component render LOG class component did mount
|
可以看到父组件渲染后,class component开始渲染,渲染完成后直接调用did mount,表示视图挂载成功,这时候是不调用did update
重新刷新父组件,带动ClassComponent的重渲染,此时的log
1 2 3
| LOG father render LOG class component render LOG class component did update
|
did mount 变成了did update,说明组件重新渲染并不代表组件卸载,而只是对组件的布局进行重计算然后调整UI树
只有在渲染中把ClassComponent剔除掉,才会触发will unmount
函数组件生命周期的实现方式
useEffect是函数式组件的副函数,能在函数式组件渲染完成后根据依赖参数选择是否被调用,而useRef在函数组件被挂载且未卸载的生命周期中持有值而不会被渲染重置,两者相结合就能实现ClassComponent对应的生命周期
useEffect接收两个参数,第一个为回调函数,第二个为依赖的参数,类型为可选数组,也就是可以没有依赖参数
1
| useEffect(setup, dependencies?)
|
而dependencies传入空数组或者不传参数是有差别的:
useEffect的setup回调函数还接受一个cleanup 函数作为返回值,它的调用时机是发生在每次调用useEffect的setup前,先调用先前设置的cleanup函数。
完整代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| const FuncComponent: FC = () => { const isFirstAppear = useRef<boolean>(true) useEffect(() => { console.log('function component did mount')
return () => { console.log('function component will unmount') } }, [])
useEffect(() => { if (isFirstAppear.current) { isFirstAppear.current = false } else { console.log('function component did update') } })
console.log('function component render')
return ( <View style={styles.container}> <Text style={styles.title}>{`function Component` }</Text> </View> ) }
|
第一次渲染的时候包含了视图挂载的hook,但是不包含did update,而带空数组的useEffect的调用跟渲染无关,只跟视图挂载跟卸载有关,所以在setup中hook mount,而在cleanup中hook unmount
接下去的渲染都只调用did update,但是不带依赖的useEffect同样在第一次渲染的时候也会调用,
所以使用一个ref去判断是否是第一次渲染,如果是则不调用,但是将该ref置为false,则下次渲染的时候就会调用did update。