修改formSubmitted依赖状态后useEffect仍未触发问题求助
问题根因
- 第一,你直接在组件顶层同步执行
setFormSubmitted(false),属于渲染过程中修改状态,React会将本次渲染周期内的所有状态更新合并批处理,你在提交时设置的setFormSubmitted(true)会和后续渲染时触发的setFormSubmitted(false)合并,最终状态没有发生变化,useEffect自然不会触发。 - 第二,useEffect的依赖数组中加入了
enteredUserName、enteredPassword两个ref对象,useRef返回的对象引用在组件整个生命周期中不会发生变化,放在依赖数组中无意义,也不会触发effect执行。 - 第三,用布尔值作为触发effect的标记本身存在缺陷,两次状态切换如果被React合并,就会出现状态变更未被监听的情况。
修复方案
- 将修改
formSubmitted状态的逻辑从组件顶层移到useEffect中,避免渲染过程中更新状态 - 清理useEffect依赖数组,移除不必要的ref对象依赖,
sendRequest如果是useHttp返回的稳定函数,也可以用useCallback包裹保证引用稳定 - 可以将布尔类型的
formSubmitted换成数字计数器,每次提交加1,彻底避免状态合并导致的监听失效问题
修改后参考代码
const Authctxn = useContext(AuthContext) // 换成计数器作为提交触发器 const [submitCount, setSubmitCount]= useState(0) const enteredUserName = useRef('') const enteredPassword = useRef('') const navigate = useNavigate() const { sendRequest, status, data: loginData, error } = useHttp(AuthAPI, false); // 处理提交逻辑的effect useEffect(()=> { // 初始渲染时submitCount为0,不执行 if(submitCount > 0) { sendRequest({ 'username': enteredUserName.current.value, 'password': enteredPassword.current.value }) } }, [submitCount, sendRequest]) // 处理请求返回结果的effect useEffect(() => { if(loginData?.data?.message) { alert(loginData.data.message) } // 这里可以加报错处理逻辑 if(error) { alert('登录失败,请重试') } }, [loginData, error]) const onLoginSubmitHandler = (event) => { event.preventDefault(); if ( enteredUserName.current.value.trim() !== "" && enteredPassword.current.value.trim() !== "" ) { // 每次提交计数器加1 setSubmitCount(prev => prev + 1) } else { alert("Please fill the login details correctly"); } }; if(Authctxn.isLoggedIn){ navigate('/TSBForm') }
内容的提问来源于stack exchange,提问作者Naveen
相关产品推荐
相关产品推荐

