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

如何结合input onChange与button onClick使用react-router useSubmit钩子?清除按钮提交异常

问题解决:React Router useSubmit清除按钮提交旧查询参数

问题原因

点击清除按钮后,输入框状态清空但提交的查询参数仍为旧值,核心原因有两点:

  1. React状态更新是异步的,调用setQ('')后,q变量不会立即更新为空字符串,此时提交表单会使用旧的状态值。
  2. 直接提交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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 15:57:02