React中fetch重复执行导致文本框数据被覆盖的解决方法
问题分析与解决方案
核心问题拆解
你的代码里有几个关键错误,直接导致了数据被修改/清除、请求逻辑异常的问题:
- useNavigate 使用错误:仅赋值了
useNavigate函数本身,未调用它获取导航实例,导致404场景下无法正常跳转 - Fetch 异步逻辑错误:将
then的返回值(setDocument的执行结果,为undefined)赋值给res,无法正确判断响应状态;且未先校验响应合法性就解析JSON - ReactQuill 状态更新错误:
onChange回调接收的是编辑后的markdown字符串,但你直接用它覆盖了原本的document对象,导致后续document?.markdown变为undefined,编辑器内容被清空 - 缺少请求取消机制:组件卸载或
params.id变化时,旧请求仍可能完成并更新状态,引发异常
修正后的代码
import React, { useState, useEffect } from "react"; import { useParams, useNavigate } from "react-router-dom"; import DocumentLayout from "../components/DocumentLayout"; import ReactQuill from "react-quill"; import "react-quill/dist/quill.snow.css"; const EditDocument = () => { const params = useParams(); // 正确调用useNavigate获取导航函数 const navigate = useNavigate(); const [loading, setLoading] = useState(true); // 明确初始状态结构,避免类型混乱 const [document, setDocument] = useState({ markdown: "" }); useEffect(() => { // 创建AbortController用于取消请求 const abortController = new AbortController(); const signal = abortController.signal; const fetchDocument = async () => { try { const response = await fetch( `http://127.0.0.1:8080/markdown?id=${params.id}`, { signal } // 关联取消信号 ); // 先处理HTTP状态码 if (response.status === 404) { navigate("/"); return; } if (!response.ok) { throw new Error(`请求失败: ${response.status}`); } const docData = await response.json(); setDocument(docData); } catch (error) { // 忽略取消请求的错误 if (error.name !== "AbortError") { console.error("获取文档失败:", error); } } finally { setLoading(false); } }; fetchDocument(); // 组件卸载或依赖变化时取消请求 return () => abortController.abort(); }, [params.id, navigate]); // 正确更新document对象的markdown属性,而非覆盖整个对象 const handleQuillChange = (markdown) => { setDocument(prev => ({ ...prev, markdown })); }; return loading ? ( <h3>Loading...</h3> ) : ( <DocumentLayout> <ReactQuill theme="snow" value={document.markdown} onChange={handleQuillChange} /> <button className="editor save-icon">Save</button> </DocumentLayout> ); }; export default EditDocument;
关键修改说明
- 修复useNavigate:调用
useNavigate()获取导航函数,确保404时能正确跳转 - 重构Fetch逻辑:
- 使用
AbortController取消未完成的请求,避免内存泄漏和旧请求干扰 - 先校验响应状态码,再解析JSON,正确处理404和请求失败的情况
- 用
try/catch捕获异常,增强代码健壮性
- 使用
- 修正状态更新逻辑:
- 给
document初始状态设置markdown属性,避免undefined导致的编辑器异常 handleQuillChange中只更新document对象的markdown属性,保留其他字段,防止状态被覆盖
- 给
- 完善useEffect依赖:添加
navigate到依赖数组,符合React Hooks的规则
额外提示
- 修复后,只要
params.id不变化,useEffect只会执行一次请求;如果params.id变化,旧请求会被自动取消,仅执行新请求 - 可通过浏览器DevTools的Network标签查看请求实际情况,确认请求次数是否符合预期,区分是真的多次请求还是状态更新导致的界面异常
内容的提问来源于stack exchange,提问作者SnowBoundShip53
相关产品推荐
相关产品推荐

