I have a toggle button to turn auto mode on and off, but I don’t know how to make react-hook-form automatically submit when this button is turned on.
I have tried document.querySelector('form').requestSubmit()
but it didn’t work.
Is there a way for them to automatically submit each time progress is completed plus with 3 seconds?
const [progress, setProgress] = useState(null)
const [autoMode, setAutoMode] = useState(false) // Use state for auto mode
const [autoInterval, setAutoInterval] = useState(null) // Use state for interval
const {
register,
handleSubmit,
formState: { isSubmitting }
} = useForm()
// Calculate interval based on start_time, end_time, and an extra 3 seconds
const calculateInterval = (startTimeStr, endTimeStr) => {
const startTime = new Date(startTimeStr).getTime() // Convert to timestamp
const endTime = new Date(endTimeStr).getTime() // Convert to timestamp
const duration = endTime - startTime // Duration in milliseconds
const extraTime = 3000 // Add 3 seconds (3000 ms)
return duration + extraTime // Total interval duration
}
// Auto mode toggle logic
const handleAutoMode = () => {
if (!autoMode && progress) {
startAutoRefinement(progress.start_time, progress.end_time)
} else {
stopAutoRefinement()
}
setAutoMode(!autoMode) // Toggle auto mode
}
// Start auto mode with dynamic interval
const startAutoRefinement = (startTime, endTime) => {
const intervalDuration = calculateInterval(startTime, endTime)
const interval = setInterval(() => {
document.querySelector('form').requestSubmit() // Automatically submits the form
}, intervalDuration)
setAutoInterval(interval) // Store interval in state
}
// Stop auto mode and clear the interval
const stopAutoRefinement = () => {
if (autoInterval !== null) {
clearInterval(autoInterval)
setAutoInterval(null)
}
}
useEffect(() => {
return () => stopAutoRefinement() // Clean up when the component unmounts
}, [])
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))
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
})
} else {
Swal.fire({
icon: 'error',
title: 'Thất bại',
text: res.response?.data[0] || 'Luyện thất bại',
showConfirmButton: false,
timer: 1500
})
}
}
Below is the form
<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={handleAutoMode}
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='' className='size-full object-contain' />
</button>
</div>
)
) : (
<AlchemyProgressBar
startTimeStr={progress.start_time}
endTimeStr={progress.end_time}
name={progress.elixir_name}
setProgressData={setProgress}
/>
)}
</form>
2
Answers
Just
useRef
to get a hand on the<form>
Element, and call its.submit()
method:The answer above is correct. I just want to add this one as well. Because you using
react-hook-form
and have access tohandleSubmit
, you can just manually called that method like this