React中如何实现每秒自动生成随机数并更新进度条渲染
问题根因
你的代码不生效有4个核心问题:
- 同时混用
setTimeout和setInterval,会导致定时器重复叠加触发,执行逻辑混乱 number是定义在组件外的普通全局变量,值修改后不会触发React组件重渲染,界面自然不会更新- 所有styled-components组件都写在
render方法内部,每次组件重渲染都会重新生成新的组件实例,既影响性能也会导致动画异常 - 没有做定时器清理逻辑,组件卸载后定时器还在后台运行会造成内存泄漏
正确实现方案
把styled组件移到组件外部避免重复创建,用组件state存储随机数值,在组件挂载时启动定时器、卸载时清除定时器,只保留一个setInterval做每秒更新即可:
import React from 'react' import styled, { keyframes } from 'styled-components' // 所有styled组件移到组件外,全局只初始化一次 const ProgressContainer = styled.div` margin-bottom: 25px; ` const Text = styled.span` font-size: 17px; font-family: Poppins; color: #fff; ` const Value = styled.span` font-size: 17px; font-family: Poppins; color: #fff; float: right; ` const ColorAnimation = keyframes` 0% {background: #04e5e5;} 10% {background: #f37055;} 20% {background: #ef4e7b;} 30% {background: #a166ab;} 40% {background: #5073b8;} 50% {background: #04e5e5;} 60% {background: #07b39b;} 70% {background: #6fba82;} 80% {background: #5073b8;} 90% {background: #1098ad;} 100% {background: #f37055;} ` const Progress = styled.div` height: 5px; border-radius: 2.5px; margin-top: 10px; transition: width 1s ease; animation: ${ColorAnimation} 10s infinite alternate; ` class ProgressBar extends React.Component { // 初始化state存储进度值 state = { number: 0 } timer = null // 组件挂载后启动定时器 componentDidMount() { this.timer = setInterval(() => { // 生成1-100的随机数,更新state触发重渲染 this.setState({ number: Math.floor((Math.random()*100)+1) }) }, 1000) } // 组件卸载前清除定时器,避免内存泄漏 componentWillUnmount() { if (this.timer) { clearInterval(this.timer) } } render() { const { text } = this.props const { number } = this.state return( <ProgressContainer> <Text>{text}</Text> <Value>{number}%</Value> <Progress style={{width: `${number}%`}}></Progress> </ProgressContainer> ) } } export default ProgressBar
关键改动说明
- 移除全局的
number变量,改用组件内部state存储进度值,调用setState更新时React会自动触发重渲染刷新界面 - 删掉重复的定时器逻辑,只保留一个
setInterval每秒生成一次随机数 - 所有styled组件移到组件外部,避免每次渲染重复创建组件实例
- 新增生命周期逻辑,组件卸载时清除定时器,防止内存泄漏
- 给Progress的width属性单独加了过渡效果,进度条变化时更顺滑,避免和颜色动画冲突
注意不要在render方法里定义styled组件,styled-components会在每次组件实例化时给新组件生成唯一类名,会导致浏览器反复重绘DOM,性能损耗非常大。
内容的提问来源于stack exchange,提问作者user1149727
相关产品推荐
相关产品推荐

