import logo from "../../../public/assets/images/spring.png";
import LoginInput from "./loginInput/loginInput";
import LoginButton from "./loginButton/LoginButton";
import { useState } from "react";
import { useNavigate } from "react-router-dom";

export default function Login() {
  const [username, setUsername] = useState("");
  const [password, setPassword] = useState("");

  const navigate = useNavigate();

  const handleSubmit = (e) => {
    e.preventDefault();
    fetch("/api/login", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ username, password }),
    })
      .then((res) => res.json())
      .then((data) => {
        if (data.message === "invalid credentials") {
          alert("invalid credentials");
          throw new Error(data.message);
        }
        navigate("/home");
      });
  };

  return (
    <div className="login">
      <div className="login__header">
        <img className="login__header__image" src={logo} alt="logo_icon" />
      </div>

      <div className="login__card">
        <div className="login__card__header">
          <span className="login__card__header__sentence">
            Please, Enter your details
          </span>
          <h4 className="login__card__header__title">Welcome</h4>
        </div>
        <form className="login__card__info" onSubmit={handleSubmit}>
          <div className="login__card__info__inputs">
            <LoginInput
              type="text"
              value={username}
              placeholder="Enter your username"
              onChange={(e) => setUsername(e.target.value)}
            />
            <LoginInput
              type="password"
              value={password}
              placeholder="Enter your password"
              onChange={(e) => setPassword(e.target.value)}
            />
          </div>
          <div className="login__card__info__buttons">
            <LoginButton label="Submit" />
            <LoginButton label="Continue with Google" />
          </div>
        </form>
      </div>
    </div>
  );
}


const express = require("express");
const dotenv = require("dotenv");

dotenv.config();
const port = process.env.PORT || 5000;
const app = express();

app.use(express.json());

app.get("/api/test", (_, res) => {
  res.json({ message: "Server connected to frontend" });
});

app.post("/api/login", (req, res) => {
  const { username, password } = req.body;

  if (username === "admin" && password === "1234") {
    res.status(200).json({ message: "Successful login" });
  } else {
    res.status(401).json({ message: "invalid credentials" });
  }
});

app.listen(port, () => console.log(Server is running on port ${port}));


import { BrowserRouter, Navigate, Route, Routes } from "react-router-dom";
import Main from "./components/Main/Main";
import Navbar from "./components/Navbar/Navbar";
import Login from "./components/Login/Login";
import { useDispatch, useSelector } from "react-redux";
import { useEffect } from "react";
import { logoutAction } from "./store/actions/actions";
import { loginAction } from "./store/actions/actions";

const PrivateRoute = ({ children }) => {
  const { isAuth } = useSelector((state) => state.user);
  return isAuth ? children : <Navigate to="/login" />;
};

function App() {
  const dispatch = useDispatch();

  useEffect(() => {
    fetch("/api/test")
      .then((value) => value.json())
      .then((data) => console.log(data.message))
      .catch((message) => {
        throw new Error(message);
      });
  }, []);

  useEffect(() => {
    const storedUser = localStorage.getItem("user");
    if (storedUser) {
      dispatch(loginAction(storedUser));
    } else {
      dispatch(logoutAction());
    }
  }, [dispatch]);

  return (
    <BrowserRouter basename="/reactSpringCopy/">
      <Routes>
        <Route
          path="/home"
          element={
            <PrivateRoute>
              <>
                <Navbar />
                <Main />
              </>
            </PrivateRoute>
          }
        />
        <Route path="/login" element={<Login />} />
      </Routes>
    </BrowserRouter>
  );
}

export default App;


Вот так я немного изменил логику приложения. Как мне грамотно изменять isAuth в коде, потому что сейчас складывается ситуация, что я его никогда не изменяю, а просто перекидываю пользователя с помощью navigate. А ещё есть useEffect:
  useEffect(() => {
    const storedUser = localStorage.getItem("user");
    if (storedUser) {
      dispatch(loginAction(storedUser));
    } else {
      dispatch(logoutAction());
    }
  }, [dispatch]);
В нём мы подтягиваем из локального стора пользователя, но мы его туда никак не помещаем