React组件,渲染计数器RenderCount组件的实现与优化
发布于 作者:苏南大叔 来源:程序如此灵动~
在React编程里面,倡导的是:组件能不渲染就不渲染。所以,就存在着Memo/useMemo/useCallback/shouldUpdate等等缓存/禁止渲染的概念了。出于调试的目的,总是希望显式的知晓对应的组件到底有没有被渲染。或者想知晓:究竟渲染了几次。那么,本文介绍的就是一个叫做RenderCount的自定义组件。可以用于统计父组件的渲染次数。

苏南大叔的“程序如此灵动”博客,记录苏南大叔的代码编程经验总结。本文测试环境:nodejs@20.18.0,create-react-app@5.0.1,react@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就完成了。代码非常简单吧?

优化:加载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;
优化: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;
css模块化这个概念,是通过webpack来实现的。当然,也并不是说必须实现这个css模块化。仅仅是做个更加靠谱的写法罢了。可以最大限度的避免不同组件的css相互影响。
构建效果
因为涉及到了css的引入及模块化问题。可以查看一下构建效果里面的实际css的表现,本文的构建是基于create-react-app的webpack@5的。效果如下:

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