React+hooks如何解决开发最基础的重复【渲染】问题?useMemo+useCallback

相信大部分React前端开发者对类组件的编程方式都有长时间的编码经验,对性能优化的方案亦有研究,如PureComponent、Component+ComponentShouldUpdate等,但随着大势所趋我们必须拥抱函数式编程+Hooks,那么我们之前的优化方案如何在函数式编程中得以实施呢?

手头的RN项目正好有一个倒计时的小需求,就梳理一下几个hooks的API,如何帮助我们如何高性能的实现。

脱敏之后的需求为:渲染12:21:01马上开抢倒计时。

我们暂且做个约定,初始化几个参数

  const countDownIntervalRef = useRef(null); // 定时器ref
  const [hour, setHour] = useState(-1); // 时
  const [minute, setMinute] = useState(-1); // 分
  const [second, setSecond] = useState(-1); // 秒
组件的重复渲染

有几个场景

  • 静态dom
    这类组件不会依赖我们的hour、minute、second变化,所以针对他们的重复渲染很有必要,这里我们采用***useMemo***来进行处理。
  /**
   * 时间组件间隙
   */
  const TimeGap = useMemo(() => {
    console.log(`${hour}:${minute}:${second}`);
    console.log('TimeGap');
    return <Text style={[Styles.timeItemText, Styles.timeGapText]}>:</Text>;
  }, []);
``

大家应该可以看出来,这串代码没别的作用,只是渲染了一个【:】,没错,就是一个冒号。

那么当倒计时运行起来之后的日志情况如何呢?
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210417215001690.png#pic_center)
没错,初始化的时候打印了一次,之后便没有重复打印。那我们优化之前的代码日志如何呢?
代码如下:
```javascript
  const TimeGap = () => {
    console.log(`${hour}:${minute}:${second}`);
    console.log('TimeGap');
    return <Text style={[Styles.timeItemText, Styles.timeGapText]}>:</Text>;
  };

日志如下:
在这里插入图片描述

相比之下就很明显了,如何这个静态dom的树足够大,那么会衍生出更严重的性能问题。
当然useMemo的用处绝不仅仅如此,我们再写个例子。

// 返回倒计时小时信息
const hourText = useMemo(() => {
	if (hour === -1) return '';
	return `${hour}小时`;
}, [hour]);

这么做的目的是当minute、second在更新的时候不要触发小时信息的重新渲染。
总结:
useMemo借助依赖项参数帮我们对函数结果进行缓存,当然不局限于return的类型,哪怕是一个component。

函数的重新生成优化

内联函数的使用让我们对函数的重复初始化越来越重视,这里我们借助useCallback来进行优化。
代码如下:

  /**
   * 计算倒计时
   */
  const calculateCountDown = useCallback(() => {
    const now = new Date().valueOf();
    let tempHour = 0;
    let tempMinute = 0;
    let tempSecond = 0;
    if (startTime >= now) {
      tempHour = Math.floor((deadline - now) / (60 * 60 * 1000));
      tempMinute = Math.floor(
        (startTime - now - tempHour * 60 * 60 * 1000) / (60 * 1000),
      );
      tempSecond = Math.floor(
        (startTime - now - tempHour * 60 * 60 * 1000 - tempMinute * 60 * 1000) /
          1000,
      );
    } else {
      clearCountDownInterval();
    }
    setHour(tempHour);
    setMinute(tempMinute);
    setSecond(tempSecond);
  }, [startTime]);

calculateCountDown是倒数时的执行函数,如果它仅仅是一个普通函数,那么可以试想,在倒计时的生命周期内这个函数每秒钟都要执行初始化和执行,而我们以useCallback进行包装,就可以将当前函数进行缓存,同时伴随依赖项startTime进行重新初始化。

总结
  • useMemo
    帮助程序缓存计算结果
  • useCallback
    帮助程序缓存函数

这些简单的例子让我们简单了解了一下这两个API,以及我们写类组件时候的优化思路如何平移过来,我们接下来会继续介绍其他API。

最后抛出一个问题,在RN项目中,我们的ListEmptyComponent会偶现闪烁的情况,大家猜想一下借助这两个API可以如何优化。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值