我们相信:世界是美好的,你是我也是。平行空间的世界里面,不同版本的生活也在继续...

React编程里面,倡导的是:组件能不渲染就不渲染。所以,就存在着Memo/useMemo/useCallback/shouldUpdate等等缓存/禁止渲染的概念了。出于调试的目的,总是希望显式的知晓对应的组件到底有没有被渲染。或者想知晓:究竟渲染了几次。那么,本文介绍的就是一个叫做RenderCount的自定义组件。可以用于统计父组件的渲染次数。

苏南大叔:React组件,渲染计数器RenderCount组件的实现与优化 - renderCount
React组件,渲染计数器RenderCount组件的实现与优化(图5-1)

苏南大叔的“程序如此灵动”博客,记录苏南大叔的代码编程经验总结。本文测试环境:nodejs@20.18.0create-react-app@5.0.1react@18.3.1

实现原理

本文RenderCount组件的实现原理,也是非常的简单。

  • 写法上就是利用了useRef()这个钩子存储计数值。因为它可以保持引用恒定,并不会因为组件渲染而重置计数。
  • 其次,这个组件就是个最简单最普通的组件,它的使用没有涉及到任何的限制,不存在Memo/useMemo/useCallback/shouldUpdate等相关概念。
  • 因为使用和写法上,都没有任何特殊之处。因此父组件更新的时候,RenderCount组件也会更新,useRef()的计数值也会加一。因此,可以非常合理的侧面反馈出父组件(所在组件)的更新次数。

基础实现代码

最简单的实现代码,就是下面这样了:

const RenderCount = function () {
  let cnt = React.useRef(0);
  return <> {++cnt.current} </>;
};

使用的时候,就是这么引用的。非常简单:

import React, { useState } from "react";
const RenderCount = function () {
  let cnt = React.useRef(0);
  return <> {++cnt.current} </>;
};
const App = function () {
  const [, setTmp] = useState();
  return (
    <>
      <button onClick={()=>setTmp(Math.random())}>强制渲染</button>
      <RenderCount />
    </>
  );
};
export default App;

最基础最简单的react渲染计数的调试组件RenderCount就完成了。代码非常简单吧?

苏南大叔:React组件,渲染计数器RenderCount组件的实现与优化 - renderCount
React组件,渲染计数器RenderCount组件的实现与优化(图5-2)

优化:加载css

稍稍优化的RenderCount版本,就是加个css动画,页面渲染的时候加个数字变化的效果。
RenderCount.css:

.render_count {
  position: relative;
  border-radius: 8px;
  background-color: #bbb;
  font-family: arial;
  font-size: 8pt;
  font-weight: bold;
  text-align: center;
  display: inline-block;
  padding: 1px 5px;
  color: white;
}
@keyframes blink1 {
  0% {
    background-color: #bbb;
  }
  50% {
    background-color: #ff9955;
  }
  100% {
    background-color: #bbb;
  }
}
@keyframes blink2 {
  0% {
    background-color: #bbb;
  }
  50% {
    background-color: #48ff00;
  }
  100% {
    background-color: #bbb;
  }
}
.render_count.odd {
  animation: blink1 1.2s ease;
}
.render_count.even {
  animation: blink2 1.2s ease;
}

RenderCount.js:

import React from "react";
import "./RenderCount.css";
const RenderCount = function () {
  let cnt = React.useRef(0);
  return (
    <span className={"render_count " + (cnt.current % 2 ? "odd" : "even")}>
      {++cnt.current}
    </span>
  );
};
export default RenderCount;

苏南大叔:React组件,渲染计数器RenderCount组件的实现与优化 - renderCount
React组件,渲染计数器RenderCount组件的实现与优化(图5-3)

优化:css模块化

create-react-app中的webpack.config.js是默认支持css模块化的,要求文件名为xxx.module.css的格式。
RenderCount.css改名为RenderCount.module.css。然后修改组件代码:
RenderCount.js

import React from "react";
import styles from "./RenderCount.module.css";
const RenderCount = function () {
  let cnt = React.useRef(0);
  return (
    <span
      className={
        styles["render_count"] +
        " " +
        (cnt.current % 2 ? styles["odd"] : styles["even"])
      }
    >
      {++cnt.current}
    </span>
  );
};
export default RenderCount;

苏南大叔:React组件,渲染计数器RenderCount组件的实现与优化 - renderCount
React组件,渲染计数器RenderCount组件的实现与优化(图5-4)

css模块化这个概念,是通过webpack来实现的。当然,也并不是说必须实现这个css模块化。仅仅是做个更加靠谱的写法罢了。可以最大限度的避免不同组件的css相互影响。

构建效果

因为涉及到了css的引入及模块化问题。可以查看一下构建效果里面的实际css的表现,本文的构建是基于create-react-appwebpack@5的。效果如下:

苏南大叔:React组件,渲染计数器RenderCount组件的实现与优化 - css模块化
React组件,渲染计数器RenderCount组件的实现与优化(图5-5)

写在最后

当然,也会有不少教程,要求把count++这个动作写到useEffect()里面。苏南大叔的实验中,这种写法会导致数字变成1就不变了。所以,暂时没有使用这种方案。

相关文章:

如果本文对您有帮助,或者节约了您的时间,欢迎打赏瓶饮料,建立下友谊关系。
本博客不欢迎:各种镜像采集行为。请尊重原创文章内容,转载请保留作者链接。

 【福利】 腾讯云最新爆款活动!1核2G云服务器首年50元!

 【源码】本文代码片段及相关软件,请点此获取更多信息

 【绝密】秘籍文章入口,仅传授于有缘之人   react