React动态环形进度条组件异常:第二个进度条静止求助
问题描述
我开发了一个独立的动态环形ProgressBar组件,在Dashboard组件中放置了两个该组件实例。其中第一个进度条运行正常,但第二个始终静止在0%且未调用进度函数。注:我使用了Tailwindcss。请帮忙修复该问题。
Dashboard组件代码
import React, { Component } from 'react' import { connect } from 'react-redux'; import { getUserInfo } from '../actions/userActions'; import { Link } from 'react-router-dom'; import ProgressBar from './progressBar'; class Dashboard extends Component { state = { user: { } } componentDidMount(){ this.props.getUserInfo(); this.setState({ user : this.props.currentUser }) } render() { const { user } = this.state; return ( <div className='w-full h-auto bg-slate-100 p-4'> { (user?.isLoggedIn == true) ? <div className='dashboard'> <div className='w-full flex h-auto mt-14'> <div className='border-2 border-slate-500 relative block text-center w-9/2 md:w-1/5 md:min-w-72 h-56 md:h-72 mr-2 mx-auto rounded-md'> <h1 className='balance text-2xl font-medium w-auto mx-auto mt-9 md:mt-20 md:font-semibold'>Personal balance</h1> <h1 className="balance text-3xl mt-6">0 $</h1> </div> <div className='border-2 border-slate-500 relative flex w-9/2 md:w-4/5 h-56 md:h-72 mx-auto rounded-md'> </div> </div> <div className='mt-2 p-2 border-2 border-slate-500 relative flex justify-between w-full h-56 md:h-64 mx-auto rounded-md'> <div className='w-28 h-28 md:w-36 md:h-36'> <ProgressBar percentage={99} /> </div> <div className='w-28 h-28 md:w-36 md:h-36'> <ProgressBar percentage={99} /> </div> </div> </div> : // NOT LOGGED PAGE <div className='w-full h-screen block mt-24'> <h1 className="text-xl text-red-500">You are not logged yet</h1> <Link to="log-in"> Login here </Link> </div> } </div> ) } } const mapUserStateToProps = (state) => { return { currentUser : state.user.user } } export default connect(mapUserStateToProps, { getUserInfo })(Dashboard);
ProgressBar组件代码
import React, { Component } from 'react' class ProgressBar extends Component { render() { let progressContainer = document.querySelector('.progress-container'); let valueContainer = document.querySelector('.progress-value'); const speed = 20; let progressValue = 0; //let progressEndValue = 70; function updateElements() { valueContainer = document.querySelector('.progress-value'); progressContainer = document.querySelector('.progress-container'); } const createProgress = setInterval(() => { updateElements(); valueContainer.innerText = `${progressValue} %` progressContainer.style.background = `conic-gradient( rgb(239 68 68) ${progressValue*3.6}deg, black 1deg, rgb(251, 202, 202) 1deg )` if (progressValue == this.props.percentage) { clearInterval(createProgress); } progressValue++; }, speed) return ( <div className='progress-container w-full h-full rounded-full flex justify-center items-center'> <div className="w-3/4 h-3/4 rounded-full bg-slate-100 flex justify-center items-center"> <h1 className='progress-value' >0 %</h1> </div> </div> ) } } export default ProgressBar;
问题原因
- 全局DOM选择器冲突:
document.querySelector只会返回页面中第一个匹配的DOM元素,第二个ProgressBar实例无法获取到自己对应的容器和数值元素,只能操作第一个实例的DOM。 - render函数内创建定时器:render函数会在组件更新时重复执行,每次执行都会新建定时器,导致逻辑混乱、内存泄漏,且无法精准控制每个实例的进度流程。
修复方案
重构ProgressBar组件
使用React状态管理+Ref操作组件内部DOM,将定时器逻辑移至生命周期函数中:
import React, { Component, createRef } from 'react' class ProgressBar extends Component { constructor(props) { super(props); this.state = { progressValue: 0 }; // 创建Ref绑定组件内部容器 this.progressContainerRef = createRef(); this.timer = null; } // 组件挂载后启动进度动画 componentDidMount() { this.startProgress(); } // 组件卸载前清除定时器,避免内存泄漏 componentWillUnmount() { if (this.timer) { clearInterval(this.timer); } } startProgress() { const speed = 20; const target = this.props.percentage; this.timer = setInterval(() => { this.setState(prevState => { const nextValue = prevState.progressValue + 1; // 到达目标值时停止定时器 if (nextValue >= target) { clearInterval(this.timer); return { progressValue: target }; } return { progressValue: nextValue }; }, () => { // 状态更新后更新容器样式 if (this.progressContainerRef.current) { this.progressContainerRef.current.style.background = `conic-gradient( rgb(239 68 68) ${this.state.progressValue * 3.6}deg, black 1deg, rgb(251, 202, 202) 1deg )`; } }); }, speed); } render() { return ( <div ref={this.progressContainerRef} className='progress-container w-full h-full rounded-full flex justify-center items-center' > <div className="w-3/4 h-3/4 rounded-full bg-slate-100 flex justify-center items-center"> <h1 className='progress-value'>{this.state.progressValue} %</h1> </div> </div> ) } } export default ProgressBar;
额外优化:Dashboard组件的用户状态同步
原代码中componentDidMount直接同步Redux状态可能会因为异步请求未完成导致数据错误,改为监听props变化:
componentDidMount(){ this.props.getUserInfo(); } componentDidUpdate(prevProps) { // 当Redux中的用户信息更新时,同步到组件state if (prevProps.currentUser !== this.props.currentUser) { this.setState({ user: this.props.currentUser }); } }
内容的提问来源于stack exchange,提问作者islam gueniari
相关产品推荐
相关产品推荐

