Как сделать изменение state при переходе между страницами с помощью стрелок

Суть, нужно сделать чтобы state нормально изменялся при переходе между страницами с помощью стрелок. Например: ты заполнил строку эмайл и перешёл на след этап ввода пароля и там если нажать стрелку назад (вернуться на страницу ввода эмайла) stage продолжит иметь статус password введите сюда описание изображения.

useView.ts

import { useForm, UseFormReturn } from 'react-hook-form'
import { emailFormScheme, EmailFormScheme } from '../constants/emailFormScheme'
import { useEffect, useState } from 'react'
import { passwordFormScheme, PasswordFormScheme } from '../constants/passwordFormScheme'
import { zodResolver } from '@hookform/resolvers/zod';
import { useNavigate } from 'react-router-dom';
import { AboutFormScheme, aboutFormScheme } from '../constants/aboutFormScheme';


export type stages = 'email' | 'password' | 'about'

export const useView = () => {

    const navigate = useNavigate()
    const [stage, setStage] = useState<stages>('email')
    const signUpForm = useForm<EmailFormScheme | PasswordFormScheme | AboutFormScheme>({
        mode: 'onBlur',
        defaultValues: {
            email: '',
            password: '',
            username: '',
            birthDate: '',
        },
        resolver: zodResolver(stage === 'email' ? emailFormScheme : stage === 'password' ? passwordFormScheme : stage === 'about' ? aboutFormScheme : emailFormScheme)
    })
    
    

    const onSubmit = signUpForm.handleSubmit(value => {
        if (stage === 'email' && 'email' in value) {
            navigate('passwordStage')
            setStage('password')
            return
        }
        if (stage === 'password' && 'password' in value) {
            navigate('aboutStage')
            setStage('about')
            return
        }
    })

    const back = () => {
        switch(stage) {
            case 'password': {
                setStage('email')
                navigate(-1)
                break
            }
            case 'about' : {
                setStage('password')
                navigate(-1)
                break
            }
        }
    }

   

    return {
        form: signUpForm,
        stage,
        functions: { onSubmit, back }
    }
}
import React from 'react'
import { Box, IconButton, Typography, useTheme } from '@mui/material'
import Header from './components/header/header'
import { useView } from './hooks/useView'
import { Outlet } from 'react-router-dom'
import { ProgressBar } from './components/progressBar/progressBar'
import ArrowBackIosIcon from '@mui/icons-material/ArrowBackIos';
import styles from './signUp.module.scss'

export type ContextType = ReturnType<typeof useView>;

export const SignUp = () => {

  const theme = useTheme()
  const { form, stage, functions } = useView()

  return (
    <Box
      width='100vw'
      height='100vh'
      display='flex'
      flexDirection='column'
      alignItems='center'
      sx={{ background: theme.palette.background.default }}
    >
      <Header />
      <Box
        width='324px'
        mt={5}
      >
        <Outlet context={{ form, functions, stage } satisfies ContextType} />
      </Box>
    </Box>
  )
}

import { SignUp, PasswordStage, EmailStage, AboutStage, StageViewer } from '@spotify/signUp'
import { createBrowserRouter } from 'react-router-dom'
import '@fontsource/roboto/300.css';
import '@fontsource/roboto/400.css';
import '@fontsource/roboto/500.css';
import '@fontsource/roboto/700.css';






export const router = createBrowserRouter([
    {
        path: '/signUp',
        element: <SignUp />,
        children: [
            {
                index: true,
                element: <EmailStage/>
            },
            {
                path: '',
                element: <StageViewer/>,
                children: [
                    {
                        path: 'passwordStage',
                        element: <PasswordStage/>
                    },
                    {
                        path: 'aboutStage',
                        element: <AboutStage/>
                    }
                ]
            }
        ]
    }
])

Ответы (1 шт):

Автор решения: Armen

браузерные стрелки не обновляют страницу(только дублируют действие каторое было совершено до), следовательно проблема не в стрелках, вот наглядный пример где state остается после переходов между страницами. Единственное что меняется это mount/unmount страницы, логично что после этого все состояние в страницах будет переинициализировано заного, если что то надо сахранить, то это должно быть вне страниц в каторых происходит mount/unmount.

если же вот прям все обновляется, наверное можно в LocalStorage либо в url дабавить данные на время

и если в целом надо сахранить stage на катором пользователь, если даже у него комп сдохнет, то это делается отправкой данных на бекенд с последуюшим получением в тот момент когда пользователь вернется обратно к форме.

import { NavLink, Outlet, createBrowserRouter } from 'react-router-dom';
import {
  createContext,
  Dispatch,
  FC,
  ReactNode,
  SetStateAction,
  useContext,
  useMemo,
  useState,
} from 'react';

type TS = {
  state: number;
  setState: Dispatch<SetStateAction<number>>;
};

const Context = createContext<TS>({} as TS);

const CountProvider = ({ children }: { children: ReactNode }) => {
  const [state, setState] = useState(0);

  const value = useMemo(() => ({ state, setState }), [state]);
  return <Context.Provider value={value}>{children}</Context.Provider>;
};

const useCountContext = () => useContext(Context);

const App = () => {
  return (
    <div>
      <NavLink to={`/contacts1`}>contacts 1</NavLink>
      <NavLink to={`/contacts2`}>contacts 2</NavLink>
      <CountProvider>
        <Outlet />
      </CountProvider>
    </div>
  );
};

const Contacts1: FC = () => {
  const { setState, state } = useCountContext();

  return (
    <div>
      <span>number : {state}</span>
      <button
        onClick={() => {
          setState((prev) => ++prev);
        }}
      >
        incr
      </button>
    </div>
  );
};

const Contacts2: FC = () => {
  const { setState, state } = useCountContext();

  return (
    <div>
      <span>number : {state}</span>
      <button
        onClick={() => {
          setState((prev) => ++prev);
        }}
      >
        incr
      </button>
    </div>
  );
};


export const router = createBrowserRouter([
  {
    path: '/',
    element: <App />,
    children: [
      {
        path: '/contacts1',
        element: <Contacts1 />,
      },
      {
        path: '/contacts2',
        element: <Contacts2 />,
      },
    ],
  },
]);
→ Ссылка