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
就不变了。所以,暂时没有使用这种方案。
相关文章:
本博客不欢迎:各种镜像采集行为。请尊重原创文章内容,转载请保留作者链接。