I have a next.js multistep form with a Stepper. Stepper has following state on the initial load:
const [steps, setStepsData] = useState([
{ name: 'Vertrag', status: 'current' },
{ name: 'Dateneingabe', status: 'upcoming' },
{ name: 'Bestätigung', status: 'upcoming' },
]);
This state is handeled in context, where I also useRouter to set my URL depending on form step. Every time user clicks next button the following functions is called:
const nextFormStep = (contract='') => {
const nextStep = formStep + 1;
router.push(`?step=${nextStep}`);
setFormValues({ contract });
};
So far so good. Now in my context I wish to check if router.asPath === '/?step=1'
then it should do smth like this:
router.asPath === '/?step=1' ? setStepsData( steps => [
{ name: 'Vertrag', status: 'current' },
{ name: 'Dateneingabe', status: 'current' },
{ name: 'Bestätigung', status: 'upcoming' },]) : console.log('doesnt work')
}, [])
So, if I just leave it like that I get an error: Too many re-renders. React limits the number of renders to prevent an infinite loop. I figured, I might need to useEffect like this:
useEffect(() => {
router.asPath === '/?step=1' ? setStepsData( steps => [
{ name: 'Vertrag', status: 'current' },
{ name: 'Dateneingabe', status: 'current' },
{ name: 'Bestätigung', status: 'upcoming' },]) : console.log('doesnt work')
}, [])
With that approach state changes only after I hit the reload button in the browser, not on changing to the next form step. How do I reach following behavior: I hit the button next step - the url path changes, state changes, I hit back button, again, the url changes and so does the steps state?
I simply needed to 'subscribe' to changes of the router as follows:
router.asPath === '/?step=1' ? setStepsData( steps => [
{ name: 'Vertrag', status: 'current' },
{ name: 'Dateneingabe', status: 'current' },
{ name: 'Bestätigung', status: 'upcoming' },]) : console.log('doesnt work')
}, [router])
Got a hint from the comment above and this SO-post: useEffect doesn't update state on route change