React hooks 可以实现 class 组件的很多功能,平时开发中我们也会经常遇到在组件渲染不同阶段执行一些业务逻辑。这类需求在 class 组件中是非常容易实现的,那么使用 hooks 是否也能实现呢,答案当然是肯定的。
下面,我们就来用 hooks 模拟 class 组件的生命周期:
class 组件 | hooks 组件 |
---|---|
constructor | useState |
getDerivedStateFromProps | 更新 useState 里面的 update 函数 |
shouldComponentUpdate | React.memo |
render | 函数本身 |
componentDidMount | useEffect |
componentDidUpdate | useEffect |
componentWillUnmount | useEffect 里面返回的函数 |
componentDidCatch | 无 |
getDerivedStateFromError | 无 |
关于useEffect中的参数问题:
useEffect 拥有两个参数,第一个参数作为回调函数会在浏览器布局和绘制完成后调用,因此它不会阻碍浏览器的渲染进程;第二个参数是一个数组。
下面是第二个参数的说明:
- 当数组存在并有值时,如果数组中的任何值发生更改,则每次渲染后都会触发回调;
- 当它不存在时,每次渲染后都会触发回调;
- 当它是一个空列表时,回调只会被触发一次,类似于 componentDidMount;
下面通过代码来做下具体的演示:
constructor
class 组件
class Example extends Component { constructor() { super(); this.state = { num: 0 } } render() { return <div>{ this.state.num }</div>; } }
函数组件不需要构造函数,可以通过调用 useState 来初始化 state
function Example() { const [num, setNum] = useState(0); return <div>{ num }</div>; }
componentDidMount
class 组件中使用 componentDidMount
class Example extends React.Component { componentDidMount() { console.log('componentDidMount!'); } render() { return null; } }
使用 hooks 模拟 componentDidMount
function Example() { useEffect(() => console.log('componentDidMount'), []); return null; }
shouldComponentUpdate
class 组件中使用 shouldComponentUpdate
shouldComponentUpdate(nextProps, nextState){ console.log('shouldComponentUpdate') // return true 更新组件 // return false 则不更新组件 }
使用 hooks 模拟 shouldComponentUpdate
const MemoComponent = React.memo( HeaderComponent, (prevProps, nextProps) => nextProps.count !== prevProps.count )
componentDidUpdate
class 组件中使用 componentDidUpdate
componentDidUpdate() { 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('didUpdate') } });
useRef 在组件中创建“实例变量”。它作为一个标志来指示组件是否处于挂载或更新阶段。当组件更新完成后在会执行 else 里面的内容,以此来单独模拟 componentDidUpdate。
componentWillUnmount
class 组件中使用 componentWillUnmount
componentWillUnmount() { console.log('componentWillUnmount'); }
使用 hooks 模拟 componentWillUnmount
useEffect(() => { return () => { console.log('willUnmount'); } }, []);