React useState未即时更新导致Screen3无法正确渲染问题
问题分析
核心问题是**screenType的赋值时机与props.products的异步更新不同步**:
- 在
handleEligibleProducts中调用props.employeeProduct(data)后,Redux更新products状态是异步操作,此时props.products还未变为目标数组,isActive依然保持初始的false。 - 紧接着直接根据
!isActive设置screenType=2,后续当props.products更新触发useEffect将isActive改为true时,没有重新触发screenType的判断逻辑,导致页面始终停留在Screen2,无法切换到Screen3。
解决方案
把screenType的判断逻辑从handleEligibleProducts末尾移到一个**依赖props.products、isActive、statusCode、productList、allEligibilityFlagZero**的useEffect中,确保关键状态变化时,自动重新计算并切换对应屏幕。同时需要将接口返回的关键变量转为组件状态,让它们能被useEffect监听。
修改后的关键代码片段
function LandingPage(props) { const [eligibleProducts, setEligibleProducts] = useState([]); const [screenType, setScreenType] = useState(); const [url, setUrl] = useState(""); const [message, setMessage] = useState(""); const [loading, setLoading] = useState(false); const [isActive, setisActive] = useState(false); // 新增状态存储接口返回的关键变量 const [statusCode, setStatusCode] = useState(null); const [productList, setProductList] = useState(null); const [allEligibilityFlagZero, setAllEligibilityFlagZero] = useState(false); const { pocBusinessEmail, pocBusinessName } = props; useEffect(() => { handleEligibleProducts(); }, []); useEffect(() => { if(props.products && props.products.filter(product => product.productStatus === 2).length > 0){ setisActive(true); } else { // 补充重置逻辑,避免状态不一致 setisActive(false); } }, [props.products]); // 新增useEffect专门处理屏幕切换逻辑 useEffect(() => { if (!statusCode) return; // 未获取接口数据时不执行 if (statusCode !== 200) { setScreenType(4); } else if (!(productList && productList.length !== 0) || allEligibilityFlagZero) { setScreenType(1); } else if (!isActive) { setScreenType(2); } else { setScreenType(3); } }, [statusCode, productList, allEligibilityFlagZero, isActive]); const handleEligibleProducts = async () => { setLoading(true); let data = { userType: 102, email: window.localStorage.getItem("email") }; try { const res = await props.getEligibleProducts(data); const { statusCode: resStatusCode, msgText, productList: resProductList, Url } = res.data.responsePayload; // 将接口返回的关键数据存入组件状态 setStatusCode(resStatusCode); setProductList(resProductList); if (Url) { setUrl(new URL(Url)); } if (resStatusCode === 200) { await props.employeeProduct({ employeeId: props.employeeId, products: null }); } if (resProductList) { setEligibleProducts(resProductList.map(product => ({ ...product, selected: false }))); const flagZero = resProductList.length && resProductList.every(product => product.eligibilityFlag === 0); setAllEligibilityFlagZero(flagZero); } if (resStatusCode !== 200) { setMessage(msgText); } setLoading(false); } catch (error) { setLoading(false); console.log("big error: " + error); } }; // 其余原有代码保持不变... }
核心改动说明
- 将接口返回的
statusCode、productList、allEligibilityFlagZero转为组件状态,确保它们能被useEffect监听。 - 新增专属useEffect,当
statusCode、productList、allEligibilityFlagZero、isActive任一状态变化时,自动重新计算screenType。这样当props.products更新触发isActive变为true时,会自动切换到Screen3。 - 补充
isActive的重置逻辑,避免特殊场景下的状态不一致问题。
内容的提问来源于stack exchange,提问作者Angela Rubchinksy
相关产品推荐
相关产品推荐

