irpas技术客

React+hooks如何解决开发最基础的重复【渲染】问题?useMemo+useCallback_孟凡涛_react hooks dom用usememo还是u

网络投稿 2247

相信大部分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可以如何优化。


1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,会注明原创字样,如未注明都非原创,如有侵权请联系删除!;3.作者投稿可能会经我们编辑修改或补充;4.本站不提供任何储存功能只提供收集或者投稿人的网盘链接。

标签: #React #hooks #我们暂且做个约定初始化几个参数 #const