简体   繁体   English

成功登录后无法阻止用户 go 返回登录页面

[英]Unable to prevent user to go back to login page after successfully logging in

I have two problems with my react app, and I think they are related to each other:我的反应应用程序有两个问题,我认为它们是相互关联的:

  1. I can't prevent user to go back to login page.我无法阻止用户 go 返回登录页面。
  2. When I am in playground page which is a protected page and I refresh the page it redirects me to login page.当我在受保护页面的游乐场页面时,我刷新页面时,它会将我重定向到登录页面。

I think the problems are related to the ProtectedRoute component.我认为这些问题与ProtectedRoute组件有关。 Here is my code:这是我的代码:

firebase.utils.js: firebase.utils.js:

import { initializeApp } from "firebase/app";
import {
  getAuth,
  createUserWithEmailAndPassword,
  signInWithEmailAndPassword,
  signOut,
  onAuthStateChanged,
} from "firebase/auth";

import { getFirestore, doc, getDoc, setDoc } from "firebase/firestore";

// Web app's Firebase configuration
const firebaseConfig = {
  apiKey: "XXXXXXX",
  authDomain: "XXXXXXX",
  projectId: "XXXXXXX",
  storageBucket: "XXXXXXX",
  messagingSenderId: "XXXXXXX",
  appId: "XXXXXXX",
  measurementId: "XXXXXXX",
};

const firebaseApp = initializeApp(firebaseConfig);

export const auth = getAuth();

export const db = getFirestore();

export const createAuthUserWithEmailAndPassword = async (email, password) => {
  if (!email || !password) return;

  return await createUserWithEmailAndPassword(auth, email, password);
};

export const signInAuthUserWithEmailAndPassword = async (email, password) => {
  if (!email || !password) return;

  return await signInWithEmailAndPassword(auth, email, password);
};

export const signOutUser = async () => await signOut(auth);

export const onAuthStateChangedListener = (callback) =>
  onAuthStateChanged(auth, callback);

sign-in-forms.jsx:登录-forms.jsx:

import { useState } from "react";
import { Link, useNavigate } from "react-router-dom";
import { Container, Form, Button } from "react-bootstrap";
import { ToastContainer, toast } from "react-toastify";
import { signInAuthUserWithEmailAndPassword } from "../../utils/firebase/firebase.utils";

import loginImg from "../../login.png";
import "./sign-in-form.scss";
import "react-toastify/dist/ReactToastify.css";

const defaultFormFields = {
  email: "",
  password: "",
};

const SignInForm = () => {
  const [formFields, setFormFields] = useState(defaultFormFields);
  const { email, password } = formFields;

  const navigate = useNavigate();

  const resetFormFields = () => {
    setFormFields(defaultFormFields);
  };

  const hadleSubmit = async (event) => {
    event.preventDefault();

    try {
      await signInAuthUserWithEmailAndPassword(email, password);

      resetFormFields();
      navigate("/playground");
    } catch (error) {
      switch (error.code) {
        case "auth/wrong-password":
          toast.error("Incorrect password for email", {
            position: toast.POSITION.TOP_CENTER,
          });
          break;
        case "auth/user-not-found":
          toast.error("No user associated with this email", {
            position: toast.POSITION.TOP_CENTER,
          });
          break;
        default:
          console.log(error);
      }
    }
  };

  const handleChange = (event) => {
    const { name, value } = event.target;
    setFormFields({ ...formFields, [name]: value });
  };

  return (
    <Container id="main-container" className="d-grid h-100">
      <ToastContainer />
      <Form
        id="sign-in-form"
        className="text-center w-300"
        onSubmit={hadleSubmit}
      >
        <img className="mb-3 mt-3 sign-in-img" src={loginImg} alt="login" />
        <Form.Group className="mb-3" controlId="sign-in-email-address">
          <Form.Control
            className="position-relative"
            type="email"
            size="lg"
            placeholder="Email"
            autoComplete="username"
            onChange={handleChange}
            name="email"
            value={email}
          />
        </Form.Group>
        <Form.Group className="mb-3" controlId="sign-in-password">
          <Form.Control
            className="position-relative"
            type="password"
            size="lg"
            placeholder="Password"
            onChange={handleChange}
            name="password"
            value={password}
          />
        </Form.Group>
        <div className="mb-3">
          <Link to="/login/reset">Reset password</Link>
        </div>
        <div className="d-grid">
          <Button variant="primary" size="lg" type="submit">
            Login
          </Button>
        </div>
      </Form>
    </Container>
  );
};

export default SignInForm;

protectedRoute.jsx - I included the navbar (Navigate component) here because the navbar must appear only on protected pages: protectedRoute.jsx - 我在这里包含了导航栏(导航组件),因为导航栏必须只出现在受保护的页面上:

import { useContext } from "react";
import { Navigate, Outlet } from "react-router-dom";

import { UserContext } from "../../../contexts/user.context";
import Navigation from "../../../routes/navigation/navigation";

const ProtectedRoute = () => {
  const { currentUser } = useContext(UserContext);

  if (!currentUser) return <Navigate to="/auth" />;
  return (
    <div>
      <Navigation />
      <Outlet />
    </div>
  );
};

export default ProtectedRoute;

user-context.jsx:用户上下文.jsx:

import { createContext, useState, useEffect } from "react";

import { onAuthStateChangedListener } from "../utils/firebase/firebase.utils";

export const UserContext = createContext({
  currentUser: null,
  setCurrentUser: () => null,
});

export const UserProvider = ({ children }) => {
  const [currentUser, setCurrentUser] = useState(null);
  const value = { currentUser, setCurrentUser };

  useEffect(() => {
    const unsubscribe = onAuthStateChangedListener((user) => {
      console.log(user);
      setCurrentUser(user);
    });

    return unsubscribe;
  }, []);

  return <UserContext.Provider value={value}>{children}</UserContext.Provider>;
};

App.js:应用程序.js:

import { Routes, Route, Navigate } from "react-router-dom";
import Authentication from "./routes/authentication/authentication";
import ProtectedRoute from "./components/common/protected-route/protectedRoute";
import Playground from "./routes/playground/playground";
import PageNotFound from "./components/common/page-not-found/pageNotFound";


function App() {
  return (
    <div>
      <Routes>
        <Route path="/" exact element={<Navigate to="/auth" />} />
        <Route element={<ProtectedRoute />}>
          <Route path="/playground" element={<Playground />} />
        </Route>
        <Route path="/auth" element={<Authentication />} />
        <Route path="/not-found" element={<PageNotFound />} />
        <Route path="*" element={<Navigate to="/not-found" />} />
      </Routes>
    </div>
  );
}

export default App;

What am I doing wrong?我究竟做错了什么? Any help is appreciated.任何帮助表示赞赏。 Thanks!谢谢!

If you want to prevent your logged in user from going to login page, add a check in SignInForm :如果您想阻止您的登录用户进入登录页面,请在SignInForm中添加一个检查:

const { currentUser } = useContext(UserContext);

// If there is a user redirect to whatever page you want:
if (currentUser) return <Navigate to="/playground" />;

return <div>Actual login page content</div>

And for your user to stay logged in after a page refresh the easiet way is to use localStorge like so:为了让您的用户在页面刷新后保持登录状态,最简单的方法是使用localStorge ,如下所示:

import { createContext, useEffect, useState } from "react";
import { onAuthStateChangedListener } from "../utils/firebase/firebase.utils";

export const UserContext = createContext({
  currentUser: null,
  setCurrentUser: () => null,
});

export const UserProvider = ({ children }) => {
  const [currentUser, setCurrentUser] = useState(
    localStorage.getItem("user") ? JSON.parse(localStorage.getItem("user")) : null
  );

  useEffect(() => {
    const unsubscribe = onAuthStateChangedListener((user) => {
      console.log(user);
      localStorage.setItem(JSON.stringify(user));
      setCurrentUser(user);
    });

    return unsubscribe;
  }, []);

  return (
    <UserContext.Provider value={(currentUser, setCurrentUser)}>{children}</UserContext.Provider>
  );
};

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM