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

使用useReducer时如何仅在表单存在错误时阻止提交?

解决React表单提交时根据验证结果阻止提交的问题

核心问题

React中useReducer(包括useState)的状态更新是异步批量处理的,调用dispatch后无法立即获取到最新的状态值,这就是你代码里console.log(state.error)始终输出旧值、判断逻辑失效的原因。

解决方案:提前获取验证结果

不需要依赖状态更新后的结果,直接在提交事件中先执行验证逻辑,拿到结果后再决定是否阻止提交,同时更新状态。这种方式更直接高效。

修改后的代码示例:

export default function App() {
  const [state, dispatch] = useReducer(formReducer, {error: null});

  return (
    <div className="App">
      <form onSubmit={onSubmit}>
        <button>btn</button>
      </form>
    </div>
  );

  function onSubmit(ev) {
    // 先执行表单验证,直接获取错误状态
    const hasError = validateForm();
    // 更新状态
    dispatch({ type: 'submitted', payload: hasError });

    // 根据验证结果决定是否阻止提交
    if (hasError) {
      ev.preventDefault();
    }
  }
  
  function formReducer(state, action) {
    switch(action.type) {
      case 'submitted': {
        return {...state, error: action.payload};
      }
      default: 
        return state;
    }
  }

  // 替换为你的实际表单验证逻辑
  function validateForm() {
    // 示例:这里模拟验证失败
    return true;
  }
}

关于react-router的fetcher.Form

fetcher.Form的事件处理逻辑和原生<form>一致,上述方案完全适用。只需将原生表单替换为fetcher.Form即可,阻止提交的逻辑不变:

import { useFetcher } from 'react-router-dom';

export default function App() {
  const [state, dispatch] = useReducer(formReducer, {error: null});
  const fetcher = useFetcher();

  return (
    <div className="App">
      <fetcher.Form onSubmit={onSubmit}>
        <button>btn</button>
      </fetcher.Form>
    </div>
  );

  // onSubmit、formReducer、validateForm 函数和上面一致
}

为什么原代码无效?

调用dispatch后,React会将状态更新加入队列,等待批量处理,此时state仍然是更新前的旧值,所以后续的if (state.error === true)判断无法拿到最新的验证结果,自然无法正确阻止提交。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 22:20:42