如何结合input onChange与button onClick使用react-router useSubmit钩子?清除按钮提交异常
问题解决:React Router useSubmit清除按钮提交旧查询参数
问题原因
点击清除按钮后,输入框状态清空但提交的查询参数仍为旧值,核心原因有两点:
- React状态更新是异步的,调用
setQ('')后,q变量不会立即更新为空字符串,此时提交表单会使用旧的状态值。 - 直接提交form元素时,React Router会从DOM表单中读取数据,而React状态更新后DOM尚未同步,导致提交的是旧的input值。
解决方案
方案1:手动构造FormData提交(推荐)
不再直接提交form元素,而是手动创建包含最新查询值的FormData,确保提交参数与状态一致:
修改SearchBar.tsx代码:
import { Form, useSubmit } from 'react-router-dom'; import { ChangeEvent, useState } from 'react'; export default function SearchBar({ query }: { query?: string }) { const submit = useSubmit(); const [q, setQ] = useState(query ?? ''); function handleChange(event: ChangeEvent<HTMLInputElement>) { const newValue = event.target.value; setQ(newValue); submitSearch(newValue); } function handleClear() { setQ(''); submitSearch(''); } function submitSearch(searchQuery: string) { const formData = new FormData(); formData.append('q', searchQuery); const isFirstSearch = searchQuery == null; submit(formData, { replace: !isFirstSearch, method: 'get', }); } return ( <Form role="search"> <input type="search" name="q" value={q} onChange={handleChange} autoComplete="off" /> {q && q.length > 0 && ( <button type="button" onClick={handleClear}> Clear </button> )} </Form> ); }
方案2:监听状态变化自动提交
通过useEffect监听查询状态的变化,状态更新后自动提交表单:
import { Form, useSubmit } from 'react-router-dom'; import { ChangeEvent, useState, useEffect } from 'react'; export default function SearchBar({ query }: { query?: string }) { const submit = useSubmit(); const [q, setQ] = useState(query ?? ''); const [isInitialRender, setIsInitialRender] = useState(true); useEffect(() => { // 跳过初始渲染时的自动提交 if (isInitialRender) { setIsInitialRender(false); return; } const formData = new FormData(); formData.append('q', q); const isFirstSearch = q == null; submit(formData, { replace: !isFirstSearch, method: 'get', }); }, [q, submit]); function handleChange(event: ChangeEvent<HTMLInputElement>) { setQ(event.target.value); } function handleClear() { setQ(''); } return ( <Form role="search"> <input type="search" name="q" value={q} onChange={handleChange} autoComplete="off" /> {q && q.length > 0 && ( <button type="button" onClick={handleClear}> Clear </button> )} </Form> ); }
关键说明
- 两种方案都通过手动构造FormData的方式,确保提交的参数是React状态中的最新值,避免了DOM与状态不同步的问题。
- 指定
method: 'get'保证查询参数会出现在URL中,与原代码行为保持一致。
内容的提问来源于stack exchange,提问作者M. Schuepbach
相关产品推荐
相关产品推荐

