При перезагрузке страницы нужно заново авторизовываться, хотя данные сохранены в localstorage

Возникла проблема, которую не могу решить уже около суток. Задача такая, что при успешной авторизации пользователя, в localstorage должно сохраняться это состояние, чтобы при перезагрузке страницы не нужно было заново авторизовываться. Само состояние сохраняется , но при обновлении страницы все равно требуется повторный вход. Проверьте пожалуйста код, что не так я написал, и что стоит переделать?

SignIn.jsx

import React, { useState, useEffect } from "react";
import { Link } from "react-router-dom";

const SignIn = ({handleAuthSuccess}) => {
  const [formData, setFormData] = useState({ nickname: '', pass: '', email: '' });
  const [formSubmitted, setFormSubmitted] = useState(false);
  const [userData, setUserData] = useState(null);
  const [authSuccess, setAuthSuccess] = useState(false);
  
  useEffect(() => {
    const auth = JSON.parse(localStorage.getItem('auth'));
    if (auth) {
      setAuthSuccess(true);
    }
  }, []);
  
  const handleSubmit = (e) => {
    e.preventDefault();
    setFormSubmitted(true);
    fetch('/api/login', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify(formData),
    })
    .then(res => {
      if (!res.ok) {
        throw new Error('Ошибка при отправке запроса');
      }
      return res.json();
    })
    .then(data => {
      if (data.login) {
        setAuthSuccess(true);
        
        fetch('/api/userData/' + formData.nickname, {
          method: 'GET',
          headers: {
              'Content-Type': 'application/json',
          },
      })
        .then(res => res.json())
        .then(userData => {
          setUserData(userData);
          handleAuthSuccess(true, userData);
          console.log('Данные пользователя получены:', userData);
      })
        .catch(error => console.error('Ошибка при получении данных пользователя:', error));
      } else {
        setAuthSuccess(false);
      }
    })
    .catch(error => {
      console.error('Произошла ошибка:', error);
      setAuthSuccess(false);
    });
  };

  const handleChange = (e) => {
    setFormData({ ...formData, [e.target.name]: e.target.value });
  };

  return (
    <div>
      <form onSubmit={handleSubmit}>
        <label>
          Никнейм:
          <input type="text" name="nickname" value={formData.nickname} onChange={handleChange} />
        </label>
        <br />
        <label>
          Пароль:
          <input type="password" name="pass" value={formData.pass} onChange={handleChange} />
        </label><br />
        <button type="submit">Войти</button>
      </form>
      {
        formSubmitted && (authSuccess ? <p>Пользователь успешно аутентифицирован!</p> : <p>Неправильные данные</p>)
      }
    </div>
  );
};

export default SignIn;

AppRouter.jsx

import React from "react";
import { Routes, Route, useNavigate } from 'react-router-dom';
import SignUp from '../pages/SignUp';
import HomePage from '../pages/HomePage';
import NotFound from '../pages/NotFound';  
import SignIn from "../pages/SignIn";
import PersonalAcc from "../pages/PersonalAcc";
import NavBar from "./NavBar";

const publicRoutes = [
    { path: '/', Component: HomePage },
    { path: '/SignUp', Component: SignUp },
    { path: '*', Component: NotFound },
    { path: '/SignIn', Component: SignIn },
];

const authRoutes = [
    { path: '/user', Component: PersonalAcc },
];

const RouteWithProps = ({ path, Component, handleAuthSuccess, ...rest }) => {
    return <Component handleAuthSuccess={handleAuthSuccess} {...rest} />;
};

const AppRouter = () => {
    const [isAuth, setIsAuth] = React.useState(false);
    const [userData, setUserData] = React.useState(null);
    const navigate = useNavigate();

    const handleAuthSuccess = (isAuthenticated, userData) => {
        if (isAuthenticated) {
            setUserData(userData);
            setIsAuth(true);
            navigate('/user');
        }
    };

    return (
        <>
        <NavBar isAuth={isAuth} userData={userData}/>
        <Routes>
            {publicRoutes.map(({ path, Component }) => (
                    <Route key={path} path={path} element={<RouteWithProps Component={Component} handleAuthSuccess={handleAuthSuccess} />} />
                ))}
            {isAuth && authRoutes.map(({ path, Component }) => (
                        <Route key={path} path={path} element={<RouteWithProps Component={Component} handleAuthSuccess={handleAuthSuccess} userData={userData}  />} />
                ))}
        </Routes>
        </>
    );
};

export default AppRouter;

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

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

Вместо хука useEffect

  useEffect(() => {
    const auth = JSON.parse(localStorage.getItem('auth'));
    if (auth) {
      setAuthSuccess(true);
    }
  }, []);

Доставайте значение прямо в момент определения начального состояния

  const [authSuccess, setAuthSuccess] = useState(() => {
    return JSON.parse(localStorage.getItem('auth')) ? true : false;
  });

Или сокращенно

const [authSuccess, setAuthSuccess] = useState(!!JSON.parse(localStorage.getItem('auth')));

Потому что useEffect отрабатывает ПОСЛЕ первого рендера. А на момент первого рендера, переменная authSuccess === false

→ Ссылка