简体   繁体   English

尝试注册或登录时与 React.js 私有路由相关的问题

[英]React.js private route related issue when trying to signup or login

I am getting this error "Cannot update a component ( BrowserRouter ) while rendering a different component ( Login ). To locate the bad setState() call inside Login " whenever I try to signUp or log in. I think this is occurring because of react router.每当我尝试注册或登录时,我都会收到此错误“无法更新组件( BrowserRouter ),同时呈现不同的组件( Login )。要在Login中找到错误的 setState() 调用”。我认为这是由于反应而发生的路由器。 But i couldn't find where I messed up.但是我找不到我搞砸的地方。 Here is the code (index.js).这是代码(index.js)。

import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import { BrowserRouter } from 'react-router-dom';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<BrowserRouter>
<React.StrictMode>
<App />
</React.StrictMode>
</BrowserRouter>
 );
 reportWebVitals();

Here is App.js这是 App.js

import "./App.css";
import Header from "./Components/Shared/Header/Header";
import "bootstrap/dist/css/bootstrap.min.css";
import Footer from "./Components/Shared/Footer/Footer";
import { Route, Routes } from "react-router-dom";
import Home from "./Components/Pages/Home/Home";
import Login from "./Components/Pages/Login/Login";
import Register from "./Components/Pages/Login/Register";
import Contact from "./Components/Pages/Contact/Contact";
import NotFound from "./Components/Pages/NotFound/NotFound";
import Blogs from "./Components/Pages/Blogs/Blogs";
import Manage from "./Components/Pages/Manage/Manage";
import Add from "./Components/Pages/Add/Add";
import Myitems from "./Components/Pages/Myitems/Myitems";
import SingleInventory from "./Components/Pages/SingleInventory/SingleInventory";
import RequireAuth from "./Components/RequireAuth";

function App() {
return (
<div>
  <Header></Header>
  <Routes>
    <Route path="/" element={<Home></Home>}></Route>
    <Route
      path="/products/:id"
      element={
        <RequireAuth>
          <SingleInventory></SingleInventory>
        </RequireAuth>}
    ></Route>
    <Route path="/manage" element={<Manage></Manage>}></Route>
    <Route path="/add" element={<Add></Add>}></Route>
    <Route path="/myitems" element={<Myitems></Myitems>}></Route>
    <Route path="/blogs" element={<Blogs></Blogs>}></Route>
    <Route path="/contact" element={<Contact></Contact>}></Route>
    <Route path="/login" element={<Login></Login>}></Route>
    <Route path="/register" element={<Register></Register>}></Route>
    <Route path="*" element={<NotFound></NotFound>}></Route>
  </Routes>
  <Footer></Footer>
  </div>
     );
   }

export default App;

Here Login.js这里登录.js

import { Icon } from "@iconify/react";
import React, { useState } from "react";
import { Button, Form } from "react-bootstrap";
import {
useSignInWithEmailAndPassword,
useSignInWithFacebook,
useSignInWithGoogle,
}   from "react-firebase-hooks/auth";
import { Link, useLocation, useNavigate } from "react-router-dom";
import auth from "../../../firebase.init";
import logo from "../../../images/login.svg";

const Login = () => {
const navigate = useNavigate();
const location = useLocation();

const from = location.state?.from?.pathname || "/";


const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [signInWithEmailAndPassword, user, loading, error] =
useSignInWithEmailAndPassword(auth);

const [signInWithGoogle, gUser, gLoading, gError] = useSignInWithGoogle(auth);
const [signInWithFacebook, fbUser, fbLoading, fbError] =
useSignInWithFacebook(auth);

const handleFormSubmit = (e) => {
e.preventDefault();
signInWithEmailAndPassword(email, password);
};

 const handleGoogleLogin = () => {
   signInWithGoogle();
  };
 const handleFbLogin = () => {
  signInWithFacebook();
 };
 if (user || fbUser|| gUser) {
 navigate(from, { replace: true });
 }
 return (
 <div style={{ minHeight: "100vh" }} className="d-flex">
  <div className="w-50 border border-1 d-flex align-items-center justify-content-center bg- 
  warning">
    <img className="w-50" src={logo} alt=""/>
  </div>
  <div className="w-50 d-flex align-items-center justify-content-center ">
    <div className="w-75 border border-1 p-5">
      <h1 className="d-inline-block pb-2 mb-4 border-1 border-dark border-bottom">
        Log in
      </h1>
      <Form className=" mx-auto" onSubmit={handleFormSubmit}>
        <Form.Group className="mb-3" controlId="formBasicEmail">
          <Form.Label>Email address</Form.Label>
          <Form.Control
            type="email"
            name="email"
            placeholder="Enter email"
            onBlur={(e)=>setEmail(e.target.value)}
          />
        </Form.Group>

        <Form.Group className="mb-3" controlId="formBasicPassword">
          <Form.Label>Password</Form.Label>
          <Form.Control
            type="password"
            name="password"
            placeholder="Password"
            onBlur={(e)=>setPassword(e.target.value)}
          />
        </Form.Group>
        <p className="text-end">Forget password</p>
        <Button className="w-100" variant="primary" type="submit">
          Log in
        </Button>
      </Form>
      <p className="text-center">
        Don't have an account?
        <Link className="text-decoration-none" to="/register">
          Sign Up
        </Link>
      </p>
      <div className="text-center ">
        <Icon onClick={handleGoogleLogin} icon="logos:google-icon" />
        <Icon
          onClick={handleFbLogin}
          className="text-primary"
          icon="fa6-brands:facebook"
        />
        <Icon icon="logos:github-icon" />
      </div>
    </div>
  </div>
</div>
     );
  };

  export default Login;

It's because you try to navigate out in the open within the Login component.这是因为您尝试在登录组件中打开导航。

if (user || fbUser|| gUser) {
 navigate(from, { replace: true });
 }

By invoking navigate here, you're causing an update in the navigation context, which in turn can trigger a rerender while Login is still rendering.通过在此处调用 navigate,您将在导航上下文中进行更新,这反过来会在 Login 仍在呈现时触发重新呈现。 To avoid this, you want to use a useEffect hook so that this is checked after the first render/as a side effect.为避免这种情况,您需要使用useEffect挂钩,以便在第一次渲染后检查它/作为副作用。

Wrap it in a useEffect to only navigate when one of those values changes:将其包装在 useEffect 中,以便仅在其中一个值发生变化时进行导航:

useEffect(() => {
 navigate(from, { replace: true });
}, [user, fbUser, gUser]);

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

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