I have these tabs for Step1 and Step2. In step1, I have this submit button to go to the next tab, it does update the URL, but the component does not update. It still stays on tab1. How can I fix this?
I kind of wanted to direct the user to the Step2 tab once the user has clicked the submit button in Step1
I recreated this in codesandbox: https://codesandbox.io/s/dawn-cloud-uxfe97?file=/src/Page.js
export default function App() {
return (
<div className="App">
<Link to="/page">
<button>Click this to go to the page</button>
</Link>
<Routes>
<Route path="/page" element={<Page />}>
<Route path="step1" element={<Step1 />} />
<Route path="step2" element={<Step2 />} />
</Route>
</Routes>
</div>
);
}
Tabs
function TabPanel(props) {
const { children, value, index, ...other } = props;
return (
<div
role="tabpanel"
hidden={value !== index}
id={`simple-tabpanel-${index}`}
aria-labelledby={`simple-tab-${index}`}
{...other}
>
{value === index && (
<Box sx={{ p: 3 }}>
<Typography component="span">{children}</Typography>
</Box>
)}
</div>
);
}
TabPanel.propTypes = {
children: PropTypes.node,
index: PropTypes.number.isRequired,
value: PropTypes.number.isRequired
};
function a11yProps(index) {
return {
id: `simple-tab-${index}`,
"aria-controls": `simple-tabpanel-${index}`
};
}
const Ordering = () => {
const navigate = useNavigate();
const [value, setValue] = React.useState(0);
const paths = ["/page/step1", "/page/step2"];
const handleChange = (event, newValue) => {
setValue(newValue);
navigate(paths[newValue]);
};
return (
<div>
<Box sx={{ borderBottom: 1, borderColor: "divider" }}>
<Tabs
value={value}
onChange={handleChange}
aria-label="basic tabs example"
>
<Tab
label="Step 1"
{...a11yProps(0)}
component={Link}
to={`/page/step1`}
/>
<Tab
label="Step 2"
{...a11yProps(1)}
component={Link}
to={`/page/step2`}
/>
</Tabs>
</Box>
<TabPanel value={value} index={0}>
<Step1 />
</TabPanel>
<TabPanel value={value} index={1}>
<Step2 />
</TabPanel>
</div>
);
};
export default Ordering;
>Solution :
You have a typo in the Step1 component, it is navigating to "/page/Step2" instead of `"/page/step2".
const Step1 = () => {
const navigate = useNavigate();
const handleSubmit = (e) => {
e.preventDefault();
navigate("/page/step2"); // <-- fix target path
};
return (
<div>
<form onSubmit={handleSubmit}>
step1
<input type="submit" />
</form>
</div>
);
};
The main issue with Page component is that is not "listening" for external route changes. You’ll need to listen for these and manually update the value state to match the current path.
Example:
const Ordering = () => {
const { pathname } = useLocation(); // <-- current path
const navigate = useNavigate();
const [value, setValue] = React.useState(0);
const paths = useMemo(() => ["/page/step1", "/page/step2"], []);
useEffect(() => {
const value = paths.indexOf(pathname);
setValue(value !== -1 ? value : 0); // <-- set the value to match path
}, [pathname, paths]);
const handleChange = (event, newValue) => {
setValue(newValue);
navigate(paths[newValue]);
};
return (
<div>
<Box sx={{ borderBottom: 1, borderColor: "divider" }}>
<Tabs
value={value}
onChange={handleChange}
aria-label="basic tabs example"
>
<Tab
label="Step 1"
{...a11yProps(0)}
component={Link}
to={`/page/step1`}
/>
<Tab
label="Step 2"
{...a11yProps(1)}
component={Link}
to={`/page/step2`}
/>
</Tabs>
</Box>
<TabPanel value={value} index={0}>
<Step1 />
</TabPanel>
<TabPanel value={value} index={1}>
<Step2 />
</TabPanel>
</div>
);
};