React

React v16.0前的生命周期

1. 组件初始化阶段

初始化state,注入props

2. 组件挂载阶段

  • componentWillMount:组件挂载到DOM前调用

  • render:根据props和state返回虚拟DOM

  • componentDidMount:组件挂载到DOM后调用

3. 组件更新阶段

  • componentWillReceiveProps:组件接收到新的props时调用,在这个钩子里调用this.setState()不会引起第二次渲染

  • shouldComponentUpdate:props或state发生变化时,渲染执行前调用,return false可阻止渲染

  • componentWillUpdate:调用render方法前执行

  • componentDidUpdate:组件更新后调用,参数为prevProps,prevState

4. 组件卸载阶段

componentWillUnmount:卸载阶段,清除定时器,清除手动创建的DOM对象

React v16.4+的生命周期

componentWillReceiveProps,componentWillUpdate废弃

getDerivedStateFromProps

getDerivedStateFromProps 会在调用 render 方法之前调用,并且在初始挂载及后续更新时都会被调用,返回一个对象来更新 state,如果返回 null 则不更新任何内容

此方法适用于罕见的用例,即 state 的值在任何时候都取决于 props

getSnapshotBeforeUpdate

getSnapshotBeforeUpdate() 在最近一次渲染输出(提交到 DOM 节点)之前调用。它使得组件能在发生更改之前从 DOM 中捕获一些信息(例如,滚动位置)。此生命周期的任何返回值将作为第三个参数传递给 componentDidUpdate()。

Hook

Hook是react 16.8的新增特性,在函数组件中也可以使用state以及其他React特性

Hook可以让我们不用修改组件结构复用状态逻辑

Hook 将组件中相互关联的部分拆分成更小的函数

自定义hook

useUpdateEffect

import { useEffect, useRef } from 'react';
/**
* 仅更新时执行
* @param {Function} effect
* @param {Array<any>} dependencies
*/
function useUpdateEffect(effect, dependencies = []) {
const isInitialMount = useRef(true);
useEffect(() => {
if (isInitialMount.current) {
isInitialMount.current = false;
} else {
effect();
}
}, dependencies);
}
export default useUpdateEffect;

useRequest

import { useState, useCallback } from 'react';
import Cache from '@/lib/cache';
// 对API请求做一层封装,loading态,请求结果的缓存
function useRequest(fetchRequest, { initData, cacheKey } = {}) {
const [res, setRes] = useState(Cache.get(cacheKey) || initData);
const [isLoading, setIsLoading] = useState(false);
const callMethod = (o) => {
setIsLoading(true);
return fetchRequest(o)
.then((r) => {
setRes(r);
if (cacheKey) {
Cache.set(cacheKey, r);
}
return r;
})
.finally(() => {
setIsLoading(false);
});
};
const callRequest = useCallback(callMethod, []);
return [callRequest, res, isLoading];
}
export default useRequest;

socket.io hook

import { useEffect, useState, useMemo } from 'react';
import io from 'socket.io-client';
const connectState = ['connect', 'reconnect'];
const failState = [
'connect_error',
'connect_timeout',
'disconnect',
'error',
'reconnect_error',
'reconnect_failed',
];
function useSocketIO(url, options, dependencies = []) {
const [connect, setConnect] = useState(false);
const socket = useMemo(() => {
return io(url, options);
}, [url, options,...dependencies]);
useEffect(() => {
connectState.forEach((state) => {
socket.on(state, () => {
console.log(state);
setConnect(true);
});
});
failState.forEach((state) => {
socket.on(state, () => {
console.log(state);
setConnect(false);
});
});
return () => {
connectState.forEach((state) => {
socket.off(state);
});
failState.forEach((state) => {
socket.off(state);
});
socket.close();
};
}, [socket]);
return [connect, socket];
}
export default useSocketIO;