ReactUse useUpdate 解析

786 阅读1分钟

介绍

返回一个函数,函数被调用时强制组件重新渲染。

源码

import { useReducer } from 'react';

const updateReducer = (num: number): number => (num + 1) % 1_000_000;

export default function useUpdate(): () => void {
  const [, update] = useReducer(updateReducer, 0);

  return update;
}

代码很简单,就是通过改变组件状态来强制组件重新渲染。看似简单但让我产生了一些疑问:

  1. useUpdate 的使用场景是什么
  2. 为什么使用 useReducer
  3. 为什么用 (num+1)%1_000_000 的方式来改变 num

思考

useUpdate 的使用场景

useUpdate 用于强制组件渲染一般和 useRef 一起使用。

利用 useRef 处理闭包陷阱

import { useUpdate } from 'react-use';
const Demo = () => {
  const countRef = useRef(0);
  const update = useUpdate();
  
  const onClick = () => {
    setTimeout(() => {
      countRef.current++
      update()
    }, 1_000);
  };

  return (
    <button onClick={onClick}>Clicked: {countRef.current}</button>
  );
};

为什么使用 useReduce

基础实现:

export default function useUpdate(): () => void {
  const [num, setNum] = useState(0)
  return () => {
    setNum(num+1)
  }
}

useCallback来返回 函数的记忆化版本,以避免在每次重新渲染组件时都重新生成一个新的函数

export default function useUpdate(): () => void {
  const [num, setNum] = useState(0)
  return useCallback(() => {
    setNum(num+1)
  },[]) 
}

使用 useReduce 来优化,因为useCallback增加了额外的 deps 变化判断,更多的内存分配,并且每次执行 render 都会声明 useCallback 的参数函数这叫 react 内联函数。

import { useReducer } from 'react';

const updateReducer = (num: number): number => (num + 1) % 1_000_000;

export default function useUpdate(): () => void {
  const [, update] = useReducer(updateReducer, 0);

  return update;
}

为什么用 (num+1)%1_000_000 的方式来改变 num

防止 num 最大值时 num+1 报错