React提交表单时如何让API请求等待未定义依赖变量赋值后再调用
问题根源
- 接口调用无顺序控制:当前代码中
carregarCursos和carregarPlanoCurso是同时触发的,carregarPlanoCurso调用时carregarCursos还没返回结果,自然拿不到课程id - React状态更新为异步批处理:即便在
carregarCursos的then回调中设置了状态,当前执行上下文的resPesquisaCurso还是旧值,不会立刻更新 - 基础逻辑错误:
filter方法返回的是匹配结果组成的数组,直接给数组取.id属性必然返回undefined- 版本过滤逻辑里误把状态更新函数
setResPesquisaDisciplina当成了状态值使用,永远拿不到正确的学科id
修复方案
我们可以用async/await控制接口调用顺序,同时直接用接口返回的即时值做参数,规避React状态更新异步的问题,优化后的代码如下:
1. 调整carregarPlanoCurso方法,改为接收参数传入课程id
async function carregarPlanoCurso(cursoId) { const response = await api.get(`cursos/${cursoId}/plano`); return response.data; }
2. 重写handleSubmit方法,控制执行顺序
async function handleSubmit({ anoLetivo1, curso1, unidadeCurricular1, dataInicio1, dataFinal1, }) { // 第一步:加载课程列表,匹配目标课程 const cursos = await carregarCursos(); // 用find替代filter,直接返回匹配的单个课程对象,而非数组 const targetCurso = cursos.find(curso => curso.nome === curso1); if (!targetCurso) { console.error('未找到匹配的课程,请检查输入'); return; } setResPesquisaCurso(targetCurso); // 第二步:并行加载学科列表和课程计划(两个接口无依赖,并行加载提升速度) const [disciplinas, planoData] = await Promise.all([ carregarDisciplinas(), carregarPlanoCurso(targetCurso.id) // 直接传入上面拿到的课程id,不依赖状态 ]); // 第三步:匹配目标学科 const targetDisciplina = disciplinas.find(disciplina => disciplina.nome === unidadeCurricular1); if (!targetDisciplina) { console.error('未找到匹配的学科,请检查输入'); return; } setResPesquisaDisciplina(targetDisciplina); // 第四步:处理课程计划过滤 setPlan(planoData); setResPesquisaPlano(planoData.filter(plano => plano.id_disci === targetDisciplina.id)); // 第五步:加载并过滤版本数据 const edicoes = await carregarEdicoes(); setResPesquisaEdicao(edicoes.filter(edicao => edicao.id_disciplina === targetDisciplina.id)); }
核心修改点说明
- 用
find替代filter获取单个匹配对象,解决数组无id属性的问题 - 用
async/await明确控制接口执行顺序,确保拿到课程id后再发起课程计划请求 - 接口参数直接使用同步获取的接口返回值,不依赖React状态,完全规避状态更新异步的问题
- 用
Promise.all并行加载无依赖的接口,减少整体请求等待时间 - 新增空值判断逻辑,避免未匹配到数据时触发额外报错
- 修正了版本过滤逻辑中误用状态更新函数的错误
内容的提问来源于stack exchange,提问作者Ruben Martins
相关产品推荐
相关产品推荐

