0
点赞
收藏
分享

微信扫一扫

React Hooks:usePrevious

千行 2021-09-24 阅读 153

今日内容要点

  1. 认识类的组件的 componentDidUpdate
  2. 实现 usePrevious hook
  3. 结合 TypeScript 封装 usePrevious
  4. 总结

前言

在项目中某些情况下,我们必须知道组件的先前状态,通过对比状态去做一些事情。

在类组件编程中,我们可以通过 componentDidUpdate 这个生命周期钩子来做到实现,但函数组件却没有这个功能,所以我们需要自己编写自定义的逻辑来实现这个功能。

我们暂且把这个组件叫做 usePrevious(),顺便说一下,它甚至可能最终出现在下一个 React 版本中,请看 官方 React 文档中所述

认识类的组件的 componentDidUpdate

componentDidUpdate 的经典模版语法长成下面这样:

componentDidUpdate(prevProps, prevState, snapshot) {
    // 典型用法 一定要出现 if 条件语句,否则容易死循环:
}

componentDidUpdate() 会在更新后会被立即调用,首次渲染不会执行此方法。当组件更新后,可以在此处对 DOM 进行操作。

一般我们会在此对更新前后的 props 进行了比较,选择在此处进行网络请求。(例如,当 props 未发生变化时,则不会执行网络请求)。

componentDidUpdate(prevProps) {
    // 典型用法(不要忘记比较 props):
    if (this.props.userID !== prevProps.userID) {
        this.fetchData(this.props.userID);
    }
}

有时,我们还会在 componentDidUpdate 中直接调用 setState(),但一定一定要注意它必须被包裹在一个条件语句里不然会导致死循环或导致额外的重新渲染,虽然用户不可见,但会影响组件性能

componentDidUpdate 生命周期钩子,它按以下顺序接受以下参数:

  • prevProps 一个包含 props 先前值的对象
  • prevState 包含先前状态值的对象
  • snapshot 接收 getSnapshotBeforeUpdate 生命周期方法返回的值,如果没有返回值则是未定义 undefined。

实现 usePrevious hook

在函数式组建中,没有任何自带的钩子可以让我们获得之前的状态,但是我们可以使用 useRef() 这个 API 实现类似的功能。

创建一个名为 usePrevious.jsx 的新文件,内容如下:

import { useRef, useEffect } from "react";

const usePrevious = value => {
    const ref = useRef();
    // useEffect 是副作用,所以会先执行 return ,然后在执行 useEffect,ref.current 的值正好完了一步。
    useEffect(() => {
        ref.current = value;
    });

    return ref.current;
};

export default usePrevious;

使用案例:

const Counter = () => {
    const [value, setValue] = React.useState(0);
    const lastValue = usePrevious(value);

    return (
        <div>
            <p>
                Current: {value} - Previous: {lastValue}
            </p>
            <button onClick={() => setValue(value + 1)}>Increment</button>
        </div>
    );
};

在这我们能明显的感觉到 usePrevious 相对于 componentDidUpdate 的简单易维护。

结合 TypeScript 封装 usePrevious

如果项目支持 TypeScript,我们还需要向自定义钩子添加一些类型:


import { useRef, useEffect } from "react";

const usePrevious = <T>(value: T): T | undefined => {
    const ref = useRef<T>();
    
    useEffect(() => {
        ref.current = value;
    });
  
    return ref.current;
};

export default usePrevious;

简单的添加了函数泛型和联合类型。

总结

在本文中,我们学习了如何在 React 中获取功能组件的先前状态,对于类组件可通过 componentDidUpdate 来实现,在函数组件中需要基于内置的 useRef 创建了自定义 usePrevious hook,如果是 React 的项目,我们还为 usePrevious 添加了类型校验。

举报

相关推荐

React Hooks —— ref hooks

react hooks

React Hooks

React Hooks解析

react hooks useReducer

React 其他 Hooks

React hooks - useEffect

0 条评论