Защищенный маршрут продолжает перенаправляться на вход после успешного входа в систему

Я реализую защищенные маршруты в своем приложении React, используя Redux для управления состоянием и React Router для маршрутизации. После успешного входа в систему я могу перейти к защищенным маршрутам. Однако когда я вручную вставляю URL-адрес и пытаюсь перейти к защищенному маршруту (например, video/1245/), меня перенаправляют обратно на страницу входа, даже если я вошел в систему.

Компонент входа:


function Login() {
    const navigate = useNavigate();
    const dispatch = useDispatch();

    const formik = useFormik<formValues>({
        initialValues: {
            email: '',
            password: ''
        },
        validationSchema: loginValidation,
        onSubmit: () => {
            axios.post('/login/', {
                email: formik.values.email,
                password: formik.values.password
            }, {
                headers: {
                    'Content-Type': 'application/json'
                }
            })
            .then((response: AxiosResponse) => {
                if (response.status === 200) {
                    toast.success('Login successful');
                    navigate('/');
                    dispatch(loginUser(response.data.userStatus));
                    try {
                        localStorage.setItem('userInfo', JSON.stringify(response.data));
                    } catch (error) {
                        toast.error('Something went wrong');
                    }
                }
            })
            .catch((error: AxiosError) => {
                toast.error(error.response?.data as string);
            });
        }
    });

    return (
 
    );
}

export default Login;

Компонент защищенной страницы:


const ProtectedPage: React.FC<ProtectedPageProps> = ({ Component }: ProtectedPageProps) => {
    const navigate = useNavigate();
    const { isUserLogin } = useSelector((state: RootState) => state.userAuth);

    useEffect(() => {
        if (!isUserLogin) {
            navigate('/login');
        }
    }, [isUserLogin]);

    return <>{isUserLogin ? Component : null}</>;
};

export default ProtectedPage;

Часть аутентификации пользователя

import { createSlice, PayloadAction } from '@reduxjs/toolkit';

export const userAuthSlice = createSlice({
    name: 'userAuth',
    initialState: {
        isUserLogin: false,
        userStatus: ''
    },
    reducers: {
        loginUser: (state, action: PayloadAction<string>) => {
            state.isUserLogin = true;
            state.userStatus = action.payload;
        },
        logoutUser: (state) => {
            localStorage.clear();
            state.isUserLogin = false;
            state.userStatus = '';
        }
    }
});

export const { loginUser, logoutUser } = userAuthSlice.actions;

export default userAuthSlice.reducer;

Компонент приложения

function App() {
  return (
    <>
      <Navbar />
      <ToastContainer />
      <Routes>
        <Route path='/' element = {<Landing />} />
        <Route path='/login' element = {<Login />} />
        <Route path='/signup' element = {<Signup />} />
        <Route path='/verification' element = {<Verification />} />
        <Route path='/verification-request' element = {<VerificationRequest />} />
        <Route path='/password-reset-request' element = {<PasswordResetRequest />} />
        <Route path='/reset-password' element = {<ResetPassword />} />
        <Route path='/password-reset-verify' element = {<PasswordResetVerify />} />
        <Route path='/upload-video' element = {<UploadVideo />} />
        <Route path='/videos/' element = {<ProtectedPage Component = {<Videos />} />} />
        <Route path='/video/:videoId' element = {<ProtectedPage Component = {<RetriveVideo />} />} />
      </Routes>
    </>
  );
}

export default App;

Проблема: Когда я вручную перехожу к защищенному маршруту после входа в систему, я перенаправляюсь на страницу входа вместо доступа к защищенному маршруту.

Что я пробовал:

  1. Подтверждено, что состояние isUserLogin корректно обновляется после входа в систему.
  2. Убедитесь, что в localStorage задана информация о пользователе после входа в систему.
  3. Проверено, что компонент ProtectedPage правильно проверяет состояние isUserLogin. Что может быть причиной перенаправления на страницу входа при переходе по защищенному маршруту вручную и как решить эту проблему?

🤔 А знаете ли вы, что...
React имеет строгую систему типов с использованием TypeScript или Flow.


2
62
1

Ответ:

Решено

Проблема в том, что состояние избыточности не является постоянным: если вы вручную загрузите защищенную страницу, она прочитает исходное состояние, которое вы настроили при создании среза.

Таким образом, решением было бы использовать localStorage вместо просто false в свойстве isUserLogin. Теперь только после входа в систему localStorage будет иметь это значение, поэтому проверка будет постоянной на всех вкладках.

import { createSlice, PayloadAction } from '@reduxjs/toolkit';

export const userAuthSlice = createSlice({
    name: 'userAuth',
    initialState: {
        isUserLogin: Boolean(window.localStorage.getItem('userInfo')), //HERE
        userStatus: ''
    },
    reducers: {
        loginUser: (state, action: PayloadAction<string>) => {
            state.isUserLogin = true;
            state.userStatus = action.payload;
        },
        logoutUser: (state) => {
            localStorage.clear();
            state.isUserLogin = false;
            state.userStatus = '';
        }
    }
});

export const { loginUser, logoutUser } = userAuthSlice.actions;

export default userAuthSlice.reducer;