Stopwatch组件无法读取useEffect中设置的offset值的解决方法
问题根因
父组件初始状态stopwatchSecondOffset为undefined,首次渲染Stopwatch组件时传入的offset值为空,useStopwatch仅会在组件挂载初始化时读取一次配置参数,后续props.offset更新不会自动重新初始化Hook,因此秒表会一直基于首次的0偏移运行。
解决方案
方案1:父组件条件渲染(最简便)
等API请求拿到偏移量之后再渲染秒表组件,避免首次渲染时offset为空,无需修改秒表组件代码:
import Stopwatch from "./Stopwatch"; import React, { useEffect, useState } from "react"; export default function App(): JSX.Element { const [stopwatchSecondOffset, setStopwatchSecondOffset] = useState<number | undefined>(); useEffect(() => { // 模拟API请求获取偏移量 setStopwatchSecondOffset(300); }, []); return ( <div className="App"> {/* 偏移量存在时才渲染秒表组件,可自定义加载态 */} {stopwatchSecondOffset !== undefined ? ( <Stopwatch offset={stopwatchSecondOffset} /> ) : ( <span>加载中...</span> )} </div> ); }
该方案不会出现秒表数值从0跳转到偏移值的情况,用户体验更好。
方案2:秒表组件监听offset变化主动重置
如果需要提前渲染秒表组件,可在秒表组件内监听offset变化,调用useStopwatch返回的reset方法更新偏移量:
import React, { useEffect } from "react"; import { useStopwatch } from "react-timer-hook"; // 定义props类型替换any,规范类型校验 interface StopwatchProps { offset?: number } export default function Stopwatch(props: StopwatchProps) { const stopwatchOffset = new Date(); stopwatchOffset.setSeconds( stopwatchOffset.getSeconds() + (props.offset ?? 0) ); const { seconds, minutes, hours, days, isRunning, start, pause, reset } = useStopwatch({ autoStart: true, offsetTimestamp: stopwatchOffset }); // 新增:监听offset变化,动态更新秒表偏移 useEffect(() => { if (props.offset === undefined) return; const newOffsetTime = new Date(); newOffsetTime.setSeconds(newOffsetTime.getSeconds() + props.offset); // reset方法第二个参数传true,代表重置后保持自动运行状态 reset(newOffsetTime, true); }, [props.offset, reset]); return ( <div className={"control-buttons to-end"}> <div className="control-button"> <div style={{ fontSize: "32px", lineHeight: "40px", marginRight: "8px" }} > <span>{hours}</span>:<span>{minutes}</span>:<span>{seconds}</span> </div> </div> </div> ); }
内容的提问来源于stack exchange,提问作者Guerrilla
相关产品推荐
相关产品推荐

