React项目Material UI Stepper路由跳转与状态异常问题咨询
问题解决方案
问题1:需两次点击才能跳转的修复
问题原因
原有代码中所有<Link>的to属性都绑定了全局共享的url状态,第一次点击StepButton仅更新url状态,第二次点击Link才能使用更新后的路径跳转,同时嵌套的点击事件也存在冲突。
修复方案
移除全局的url状态,改用React Router的编程式导航,点击StepButton的同时完成状态更新和路由跳转,避免事件冲突。
- 首先导入路由导航方法:
import { useNavigate } from 'react-router-dom'
- 组件内声明导航实例并修改点击逻辑:
const navigate = useNavigate() const handleStep = (step: number) => () => { setActiveStep(step); const targetUrl = getStepContent(step); navigate(targetUrl); };
- 移除组件渲染中的
<Link>嵌套,修改后的Step部分代码如下:
<Step key={label}> <StepButton onClick={handleStep(index)}> <StepLabel classes={{ label: classes.label, active: classes.labelActive}} StepIconProps={{ classes: { root: classes.icon, text: classes.iconText, active: classes.iconActive}, }}> {label} </StepLabel> </StepButton> </Step>
问题2:页面加载后activeStep重置的修复
问题原因
组件的useState状态仅存在于组件生命周期中,路由跳转后Stepper组件重新挂载,状态会回到初始值。
修复方案
从当前路由路径反推对应的步骤索引,作为activeStep的初始值,同时监听路由变化同步更新状态。
- 导入路由路径监听方法:
import { useLocation } from 'react-router-dom'
- 新增路径匹配逻辑,同步步骤状态:
const location = useLocation(); // 匹配当前路由对应的步骤索引 const getCurrentStep = () => { const currentPath = location.pathname; for (let i = 0; i < 4; i++) { if (getStepContent(i) === currentPath) return i; } return 0; } // 初始化activeStep时直接匹配当前路由 const [activeStep, setActiveStep] = useState(getCurrentStep()); // 监听路由变化,同步更新activeStep useEffect(() => { setActiveStep(getCurrentStep()); }, [location.pathname]);
完整修改后代码示例
import { useNavigate, useLocation } from 'react-router-dom'; import { useEffect, useState } from 'react'; // MUI相关导入保持原有逻辑不变 function getSteps() { return ['page1', 'page2', 'page3', 'page4']; } function getStepContent(step: number) { switch (step) { case 0: return "/page1" case 1: return "/page2" case 2: return "/page3" case 3: return "/page4" default: return "/page1" } } export default function HorizontalNonLinearStepper() { const classes = useStyles(); const navigate = useNavigate(); const location = useLocation(); const steps = getSteps(); // 匹配当前路由对应的步骤索引 const getCurrentStep = () => { const currentPath = location.pathname; for (let i = 0; i < 4; i++) { if (getStepContent(i) === currentPath) return i; } return 0; } const [activeStep, setActiveStep] = useState(getCurrentStep()); // 监听路由变化同步步骤状态 useEffect(() => { setActiveStep(getCurrentStep()); }, [location.pathname]); const handleStep = (step: number) => () => { setActiveStep(step); navigate(getStepContent(step)); }; return ( <div className={classes.root}> <Stepper nonLinear activeStep={activeStep} className={classes.stepper}> {steps.map((label, index) => ( <Step key={label}> <StepButton onClick={handleStep(index)}> <StepLabel classes={{ label: classes.label, active: classes.labelActive}} StepIconProps={{ classes: { root: classes.icon, text: classes.iconText, active: classes.iconActive}, }}> {label} </StepLabel> </StepButton> </Step> ))} </Stepper> </div> ); }
内容的提问来源于stack exchange,提问作者park
相关产品推荐
相关产品推荐

