React多步骤表单导航异常:Context未完成更新即跳转
问题
使用React、react-hook-form和react-query构建多步骤订单表单,初始包含客户信息、产品选择、订单总结三个可见步骤,根据所选产品会在产品选择与订单总结间动态显示1-5个额外步骤。采用React Context跟踪订单数据与可用步骤,完成每一步后调用后端API,后端返回完整订单对象用于更新OrderContext中的orderData,之后跳转至下一个合适步骤。
当前问题:跳转操作在OrderContext完全更新前执行,导致用户被导向订单总结页,而非产品选择后应新增的步骤。因后端会添加前端请求外的订单数据,无法使用乐观更新,必须依赖API返回对象。
解决方案
方案一:让goToNextStep基于最新订单数据计算下一步
当前goToNextStep依赖组件渲染时的currentStepIndex和visibleSteps,这两个值在orderData更新后不会立即更新。修改goToNextStep,允许传入最新的订单数据,直接基于该数据计算可见步骤和下一步:
- 修改OrderContext中的
goToNextStep方法:
const goToNextStep = (targetOrderData?: IInternalApiDetailOrderResponseBody) => { const data = targetOrderData || orderData; if (!data) return; // 基于传入的最新数据计算可见步骤 const updatedVisibleSteps = orderStepsData.filter(step => step.isVisible(data)); // 获取当前步骤(保持原逻辑,优先从路径匹配) const currentStepInUpdated = findStepByPath(currentPath) || updatedVisibleSteps[0]; const currentIndex = updatedVisibleSteps.findIndex(step => step.id === currentStepInUpdated.id); if (currentIndex < updatedVisibleSteps.length - 1) { const nextStep = updatedVisibleSteps[currentIndex + 1]; navigate(`/orders/${orderId}/edit/${nextStep.path}`); } };
- 在表单的
onSuccess中调用goToNextStep时传入新的订单数据:
onSuccess(data) { const newOrderData = data.data.result; updateOrderData(newOrderData); goToNextStep(newOrderData); // 直接用新数据计算下一步 }
这种方式不需要等待组件重渲染,直接基于最新数据计算跳转目标,避免旧数据导致的错误跳转。
方案二:通过状态标记+useEffect等待组件更新后跳转
利用React的状态和副作用钩子,在orderData更新完成后再执行跳转:
- 在OrderContextProvider中添加状态并修改
updateOrderData:
import { useState, useEffect } from 'react'; export const OrderContextProvider = ({ children }: { children: React.ReactNode }) => { // ... 其他现有代码 const [shouldNavigateNext, setShouldNavigateNext] = useState(false); const updateOrderData = (updatedOrderData: IInternalApiDetailOrderResponseBody) => { queryClient.setQueryData(['order', orderId], updatedOrderData); setShouldNavigateNext(true); // 标记需要跳转 }; // 监听orderData和跳转标记,更新完成后执行跳转 useEffect(() => { if (shouldNavigateNext && orderData) { goToNextStep(); setShouldNavigateNext(false); // 重置标记 } }, [shouldNavigateNext, orderData, goToNextStep]); // ... 其他现有代码 };
- 修改表单的
onSuccess,只更新订单数据,不再手动调用跳转:
onSuccess(data) { updateOrderData(data.data.result); }
这种方式利用React的渲染周期,确保visibleSteps和currentStepIndex都基于最新的orderData计算完成后,再执行跳转逻辑。
内容的提问来源于stack exchange,提问作者Thore
相关产品推荐
相关产品推荐

