ReactJS中基于Countdown Timer的If条件判断不生效问题
问题根因
你的条件判断失效是写法违背React基本运行逻辑导致的,具体问题:
- 原
Countdown函数无返回值,组件外层初始化拿到的distance是undefined,定时器内部更新的distance是函数局部变量,Home组件完全无法感知值的变化,自然不会触发重渲染更新按钮状态 - 直接用
document.getElementById操作DOM的写法和React状态驱动视图的机制冲突,倒计时更新时不会同步刷新组件内的判断逻辑 - 原逻辑没有做定时器清理,组件卸载后定时器仍会运行,存在内存泄漏问题
- JSX里混用了
class和className属性,会触发控制台警告,React中元素类名必须统一用className声明
修复方案
把倒计时逻辑改写成React自定义Hook,通过状态管理倒计时值,组件可以实时拿到最新的剩余时间触发重渲染。
第一步:重写Countdown.js为自定义Hook
import { useState, useEffect } from 'react'; function useCountdown(targetDate) { // 初始化时计算首次剩余时间差 const [distance, setDistance] = useState(() => new Date(targetDate).getTime() - Date.now()); useEffect(() => { const timer = setInterval(() => { const leftTime = new Date(targetDate).getTime() - Date.now(); setDistance(leftTime); // 倒计时归0时清除定时器 if (leftTime < 0) clearInterval(timer); }, 1000); // 组件卸载时清理定时器,避免内存泄漏 return () => clearInterval(timer); }, [targetDate]); // 计算格式化展示时间 const days = Math.floor(distance / (1000 * 60 * 60 * 24)); const hours = Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)); const minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60)); const seconds = Math.floor((distance % (1000 * 60)) / 1000); const displayText = distance < 0 ? "Mint is Live!" : `${days}d ${hours}h ${minutes}m ${seconds}s`; return { distance, displayText }; } export default useCountdown;
第二步:修改Home页面调用逻辑
移除组件外的无效调用,在组件内部引入Hook拿到实时状态,直接通过状态渲染视图,删除原生DOM操作代码:
import React from 'react'; import '../../App.css'; import useCountdown from '../Countdown'; function Home() { // 传入目标倒计时时间,获取实时剩余时间和展示文本 const { distance, displayText } = useCountdown("Jun 27, 2022 22:27:10"); return ( <> <div className="App"> <div> <div className='hero-container'> <div className="courses-container"> <div className="course"> <div className="course-preview"> <h6>Welcome</h6> <h2>PROJECT NAME</h2> </div> <div className="course-info"> <div className="progress-container"> <span className="progress-text">/1000</span> </div> {/* 直接渲染状态中的倒计时文本 */} <h2 id="demo">{displayText}</h2> <div id='input-number' className='input-number-location'> <input className='input-number button' type="number" name="amount" defaultValue="1" min="1" max="20"/> </div> {/* 状态实时更新,条件判断会正常触发重渲染切换按钮 */} {distance < 0 ? <button className="btncard">OPEN</button> : <button className="btncard">APP CLOSED</button> } </div> </div> </div> </div> </div> </div> </> ); } export default Home;
内容的提问来源于stack exchange,提问作者drdro
相关产品推荐
相关产品推荐

