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

React Hook Form自动提交问题:自动模式下进度完成+3秒提交

解决方案

核心问题是你通过DOM操作触发表单提交的方式没有正确对接react-hook-form的提交逻辑,直接调用react-hook-form提供的handleSubmit包装后的提交函数即可解决,同时调整自动提交的触发时机,确保每次进度完成后延迟3秒再提交。

修改步骤

  1. 直接调用react-hook-form的提交函数:
    不需要通过document.querySelector('form').requestSubmit(),直接使用handleSubmit(onSubmit)()就能触发表单提交,这是react-hook-form官方推荐的程序化提交方式,完全适配表单验证和提交流程。

  2. 调整自动提交的定时器逻辑:
    当进度完成后(AlchemyProgressBar调用setProgressData(null)),通过监听progress状态变化,在新进度生成且自动模式开启时,重新设置延迟提交定时器,实现循环自动提交。

修改后的完整代码

组件逻辑部分

import { useState, useEffect } from 'react';
import { useForm } from 'react-hook-form';
import Swal from 'sweetalert2';
import AlchemyService from './path-to-your-alchemy-service';
import AlchemyProgressBar from './path-to-your-AlchemyProgressBar';
import Furnace from './path-to-your-furnace-image';

const AlchemyComponent = () => {
  const [progress, setProgress] = useState(null);
  const [autoMode, setAutoMode] = useState(false);
  const [autoTimer, setAutoTimer] = useState(null);

  const {
    register,
    handleSubmit,
    formState: { isSubmitting }
  } = useForm();

  // 计算延迟时间:进度时长 + 额外3秒
  const calculateDelay = (startTimeStr, endTimeStr) => {
    const startTime = new Date(startTimeStr).getTime();
    const endTime = new Date(endTimeStr).getTime();
    const duration = endTime - startTime;
    const extraTime = 3000; // 3秒延迟
    return duration + extraTime;
  };

  // 触发表单提交的函数
  const triggerFormSubmit = () => {
    handleSubmit(onSubmit)();
  };

  // 启动自动提交定时器
  const startAutoSubmit = () => {
    if (!progress) return;
    
    const delay = calculateDelay(progress.start_time, progress.end_time);
    const timer = setTimeout(() => {
      triggerFormSubmit();
    }, delay);

    setAutoTimer(timer);
  };

  // 停止自动提交
  const stopAutoSubmit = () => {
    if (autoTimer) {
      clearTimeout(autoTimer);
      setAutoTimer(null);
    }
  };

  // 切换自动模式
  const handleAutoModeToggle = () => {
    if (!autoMode) {
      startAutoSubmit();
    } else {
      stopAutoSubmit();
    }
    setAutoMode(!autoMode);
  };

  // 监听进度和自动模式变化,自动启动/停止定时器
  useEffect(() => {
    if (autoMode && progress) {
      startAutoSubmit();
    }
    return () => stopAutoSubmit();
  }, [autoMode, progress]);

  // 表单提交逻辑
  const onSubmit = async (data) => {
    if (!data.elixir) {
      Swal.fire({
        icon: 'error',
        title: 'Lỗi',
        text: 'Vui lòng chọn đan dược để luyện!',
        showConfirmButton: false,
        timer: 1500
      });
      return;
    }

    const formData = new FormData();
    formData.append('elixir_id', parseInt(data.elixir));

    try {
      const res = await AlchemyService.createElixir(formData);
      if (res.status === 201) {
        Swal.fire({
          icon: 'success',
          title: 'Thành công',
          text: `Luyện thành công`,
          showConfirmButton: false,
          timer: 1500
        });
        // 提交成功后,根据后端返回的新进度数据更新状态(需根据实际接口调整)
        // setProgress(res.data.progress);
      } else {
        throw new Error(res.response?.data[0] || 'Luyện thất bại');
      }
    } catch (error) {
      Swal.fire({
        icon: 'error',
        title: 'Thất bại',
        text: error.message,
        showConfirmButton: false,
        timer: 1500
      });
      // 提交失败时自动关闭自动模式(可选,根据需求调整)
      stopAutoSubmit();
      setAutoMode(false);
    }
  };

  return (
    <form onSubmit={handleSubmit(onSubmit)} className='flex flex-col gap-3 font-medium text-gray-600'>
      {/* 表单选项部分 */}
      {list.map((item, index) => (
        <div key={index} className='flex flex-col gap-1'>
          <div className='flex items-center gap-1'>
            <input type='radio' {...register('elixir')} value={item.elixir.id} id={`dan-duoc-${index}`} />
            <label htmlFor={`dan-duoc-${index}`} className='font-medium text-yellow-600'>
              <span>{item.elixir.name}</span> (độ thành thục: {item.proficiency} %)
            </label>
          </div>
          <p className='text-sm text-gray-600'>
            <i>
              <span className='font-bold text-gray-700'>Đan dược này cần:</span> {item.description}
            </i>
          </p>
          <p className='text-sm text-gray-600'>
            Thời gian luyện: <b>{Math.ceil(parseInt(item.elixir.crafting_time) / 60)}</b> giờ
          </p>
        </div>
      ))}

      {/* 自动模式切换按钮 */}
      <button
        type='button'
        onClick={handleAutoModeToggle}
        className={`px-2 py-1 ${autoMode ? 'bg-red-500' : 'bg-primary'} text-white font-medium rounded w-fit`}
      >
        {autoMode ? 'Tắt auto luyện đan' : 'Bật auto luyện đan'}
      </button>

      {/* 进度/提交按钮区域 */}
      {progress === null ? (
        isSubmitting ? (
          <p>Đang tải...</p>
        ) : (
          <div className='w-full flex justify-center items-center mt-10'>
            <button type='submit' className='size-60'>
              <img src={Furnace} alt='Luyện đan' className='size-full object-contain' />
            </button>
          </div>
        )
      ) : (
        <AlchemyProgressBar
          startTimeStr={progress.start_time}
          endTimeStr={progress.end_time}
          name={progress.elixir_name}
          setProgressData={setProgress}
        />
      )}
    </form>
  );
};

export default AlchemyComponent;

关键说明

  • 替代DOM提交:使用handleSubmit(onSubmit)()直接触发提交,避免DOM操作带来的元素未找到、提交逻辑不匹配等问题。
  • 状态驱动定时器:通过useEffect监听progress和autoMode状态,确保每次新进度生成时自动设置延迟提交,实现循环自动提交逻辑。
  • 错误处理优化:提交失败时自动关闭自动模式,避免重复失败提交,提升用户体验。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 11:17:32