You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从react-timer-hook的Timer组件获取当前已用分钟数?

解决Next.js中react-timer-hook计时器在表单提交时获取已用分钟数的问题

方案一:修改Timer组件,在到期回调中传递已用时间

这种方案无需调整组件结构,只需在Timer组件内计算已用时间并传递给handleForm:

  1. 更新Timer组件:
    接收父组件传入的总时长,计算已用时间后通过回调函数传递给父组件:

    import { Typography } from '@mui/material';
    import { useTimer } from 'react-timer-hook';
    
    export default function Timer({ expiryTimestamp, functionCall, totalDuration }) {
        const { seconds, minutes, hours } = useTimer({
            expiryTimestamp,
            onExpire: () => {
                // 计算剩余秒数
                const remainingSeconds = hours * 3600 + minutes * 60 + seconds;
                // 转换为已用分钟数
                const usedMinutes = (totalDuration - remainingSeconds) / 60;
                // 将结果传递给表单处理函数
                functionCall(usedMinutes);
            }
        });
    
        return (
            <Typography variant='h5' fontWeight={'bold'} component={'div'}>
                <span>{hours < 10 ? '0' + hours : hours}</span>:<span>{minutes < 10 ? '0' + minutes : minutes}</span>:<span>{seconds < 10 ? '0' + seconds : seconds}</span>
            </Typography>
        );
    }
    
  2. 调整Timer组件调用方式:
    传入总时长(示例中为3600秒,即1小时):

    const totalDuration = 3600;
    const time = new Date();
    time.setSeconds(time.getSeconds() + totalDuration);
    <Timer functionCall={handleForm} expiryTimestamp={time} totalDuration={totalDuration} />
    
  3. 修改handleForm函数:
    接收传递的已用分钟数并赋值给total_time_taken:

    async function handleForm(total_time_taken) {
        const token = Cookies.get('token');
        const formData = {
            user_id: userId,
            test_id: test_id,
            total_time_taken: Math.round(total_time_taken), // 可根据需求取整或保留小数
            answers: answers
        };
        const data = JSON.stringify(formData);
        const resp = await axios.post(`answers`, data, {
            headers: {
                Authorization: `Bearer ${token}`
            }
        });
        if (resp.data.success) {
            router.push('/user/feedback/' + test_id);
        }
    }
    

方案二:状态提升,将计时器状态移到父组件

把useTimer的状态管理放到父组件中,Timer组件仅负责展示时间,让handleForm直接访问计时器数据:

  1. 更新父组件逻辑:
    引入useTimer并管理状态,直接在handleForm内计算已用时间:

    import { useTimer } from 'react-timer-hook';
    
    // ...
    
    const totalDuration = 3600;
    const time = new Date();
    time.setSeconds(time.getSeconds() + totalDuration);
    // 父组件初始化计时器
    const { seconds, minutes, hours } = useTimer({
        expiryTimestamp: time,
        onExpire: handleForm
    });
    
    async function handleForm() {
        const token = Cookies.get('token');
        // 计算已用分钟数
        const remainingSeconds = hours * 3600 + minutes * 60 + seconds;
        const total_time_taken = (totalDuration - remainingSeconds) / 60;
    
        const formData = {
            user_id: userId,
            test_id: test_id,
            total_time_taken: Math.round(total_time_taken),
            answers: answers
        };
        const data = JSON.stringify(formData);
        const resp = await axios.post(`answers`, data, {
            headers: {
                Authorization: `Bearer ${token}`
            }
        });
        if (resp.data.success) {
            router.push('/user/feedback/' + test_id);
        }
    }
    
  2. 简化Timer组件:
    仅接收父组件传递的时间参数并渲染:

    import { Typography } from '@mui/material';
    
    export default function Timer({ hours, minutes, seconds }) {
        return (
            <Typography variant='h5' fontWeight={'bold'} component={'div'}>
                <span>{hours < 10 ? '0' + hours : hours}</span>:<span>{minutes < 10 ? '0' + minutes : minutes}</span>:<span>{seconds < 10 ? '0' + seconds : seconds}</span>
            </Typography>
        );
    }
    
  3. 调用简化后的Timer组件:

    <Timer hours={hours} minutes={minutes} seconds={seconds} />
    

内容的提问来源于stack exchange,提问作者DCodeMania

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 23:24:31