【问题标题】:Routes not resolving with Reactjs using Firebase Auth使用 Firebase Auth 无法通过 Reactjs 解析的路由
【发布时间】:2021-11-21 13:50:27
【问题描述】:

背景

我正在构建一个带有 Reactjs 和 Firebase 后端/身份验证的网络应用程序。我已经设置和 AuthContextProvider 并使用 React Router 进行导航。

问题

没有一个路由正在解析。

代码

// App.js
import React from "react";
import {
  BrowserRouter as Router,
  Route,
  Link,
  Redirect,
} from "react-router-dom";
import { AuthContextProvider, useAuthState } from "./firebase";

import Navigation from "./components/layout/Navigation";
import Landing from "./components/screens/Landing";
import SignUp from "./components/screens/SignUp";
import SignIn from "./components/screens/SignIn";
import ForgotPassword from "./components/screens/ForgotPassword";
import Home from "./components/screens/Home";
import Profile from "./components/screens/Profile";
import Account from "./components/screens/Account";
import Admin from "./components/screens/Admin";

import * as ROUTES from "./constants/routes";

const AuthenticatedRoute = ({ component: C, ...props }) => {
  const { isAuthenticated } = useAuthState();
  console.log(`AuthenticatedRoute: ${isAuthenticated}`);
  return (
    <Route
      {...props}
      render={(routeProps) =>
        isAuthenticated ? <C {...routeProps} /> : <Redirect to="/login" />
      }
    />
  );
};
const UnauthenticatedRoute = ({ component: C, ...props }) => {
  const { isAuthenticated } = useAuthState();
  console.log(`UnauthenticatedRoute: ${isAuthenticated}`);
  return (
    <Route
      {...props}
      render={(routeProps) =>
        !isAuthenticated ? <C {...routeProps} /> : <Redirect to="/home" />
      }
    />
  );
};

const App = () => (
  <AuthContextProvider>
    <Router>
      <Navigation />
      <UnauthenticatedRoute exact path={ROUTES.SIGN_UP} component={SignUp} />
      <UnauthenticatedRoute exact path={ROUTES.SIGN_IN} component={SignIn} />
      <UnauthenticatedRoute
        exact
        path={ROUTES.PASSWORD_RESET}
        component={ForgotPassword}
      />
      <UnauthenticatedRoute exact path={ROUTES.LANDING} component={Landing} />

      <AuthenticatedRoute exact path={ROUTES.ACCOUNT} component={Account} />
      <AuthenticatedRoute exact path={ROUTES.ADMIN} component={Admin} />
      <AuthenticatedRoute exact path={ROUTES.PROFILE} component={Profile} />
      <AuthenticatedRoute exact path={ROUTES.HOME} component={Home} />
    </Router>
  </AuthContextProvider>
);

export default App;
// firebase.js
import { getAuth, onAuthStateChanged } from "@firebase/auth";
import { initializeApp } from "firebase/app";
import { getFirestore } from "firebase/firestore";
import { useState, useEffect, useContext, createContext } from "react";

const firebaseConfig = {
  ...
};

export const firebaseApp = initializeApp(firebaseConfig);
const db = getFirestore();

export const AuthContext = createContext();

export const AuthContextProvider = (props) => {
  const [user, setUser] = useState();
  const [error, setError] = useState();

  useEffect(() => {
    const unsubscribe = onAuthStateChanged(getAuth(), setUser, setError);
    return () => unsubscribe();
  }, []);
  return <AuthContext.Provider value={{ user, error }} {...props} />;
};

export const useAuthState = () => {
  const auth = useContext(AuthContext);
  return { ...auth, isAuthenticated: auth.user != null };
};
// routes.js
export const LANDING = "/";
export const SIGN_UP = "/signup";
export const SIGN_IN = "/login";
export const HOME = "/home";
export const ACCOUNT = "/account";
export const ADMIN = "/admin";
export const PASSWORD_RESET = "/forgot-password";
export const PROFILE = "/profile";
// Navigation.js
import React from "react";
import { Link } from "react-router-dom";
import { getAuth, signOut } from "firebase/auth";
import { useAuthState } from "../../firebase";

import * as ROUTES from "../../constants/routes";

import Navbar from "react-bootstrap/Navbar";
import Container from "react-bootstrap/Container";
import Nav from "react-bootstrap/Nav";
import NavDropdown from "react-bootstrap/NavDropdown";

const Navigation = () => {
  const { user } = useAuthState();
  return (
    <div className="navigation">
      <Navbar bg="light" expand="lg">
        <Container>
          <Link to={ROUTES.HOME}>
            <Navbar.Brand>Underground</Navbar.Brand>
          </Link>
          <Navbar.Toggle aria-controls="basic-navbar-nav" />
          <Navbar.Collapse id="basic-navbar-nav">
            <Nav className="me-auto">
              {user ? (
                <NavDropdown title={user?.email} id="basic-nav-dropdown">
                  <Link to={ROUTES.ACCOUNT}>
                    <NavDropdown.Item>Account</NavDropdown.Item>
                  </Link>
                  <NavDropdown.Divider />
                  <NavDropdown.Item onClick={() => signOut(getAuth())}>
                    Logout
                  </NavDropdown.Item>
                </NavDropdown>
              ) : (
                <NavDropdown title="Users" id="basic-nav-dropdown">
                  <Link to={ROUTES.SIGN_IN}>
                    <NavDropdown.Item>Sign in</NavDropdown.Item>
                  </Link>
                  <Link to={ROUTES.SIGN_UP}>
                    <NavDropdown.Item>Signup</NavDropdown.Item>
                  </Link>
                </NavDropdown>
              )}
            </Nav>
          </Navbar.Collapse>
        </Container>
      </Navbar>
    </div>
  );
};

export default Navigation;

那为什么不解决呢?

我认为我的路由器没有任何配置错误,为什么路由无法解析?对于经过身份验证的用户,它们要么解析为 /home,要么为未经过身份验证的用户解析为 /login,这表明与重定向有关?

https://codesandbox.io/s/nostalgic-resonance-uptre

【问题讨论】:

    标签: reactjs firebase-authentication react-router


    【解决方案1】:

    我设法解决了这个问题。问题与 React 路由器无法正常工作无关,而在于使用的 react-bootstrap 语法。我不确定是什么导致了冲突,但以下解决方案已修复它。

    我在这里找到了答案:ReactJS Bootstrap Navbar and Routing not working together

    简而言之,您不需要在&lt;Nav.Link&gt;...&lt;/Nav.Link&gt; 中插入&lt;Link to=""&gt;...&lt;/Link&gt;,只需在&lt;Nav.Link&gt; 中添加as={Link} to={...},或者如果您愿意,可以添加任何其他组件。

    【讨论】:

      【解决方案2】:

      您需要用 Switch 组件包装您的 Route 组件,例如。

      <Router>
      <Link></Link>
      <Link></Link>
      <Switch>
        <Route/>
        <Route/>
      </Switch>
      <Router/>
      
      

      见官方guide

      【讨论】:

      • 啊,是的,我现在添加了一个 Switch 组件,但这并没有解决问题。它的行为仍然与以前相同。
      • @Anthony 你可以创建一个代码框并将其链接到这里吗?
      • 沙盒位于codesandbox.io/s/nostalgic-resonance-uptre - Firebase 配置是从 env 文件中获取的(不在沙盒中)。
      猜你喜欢
      • 2021-04-04
      • 1970-01-01
      • 2018-06-29
      • 1970-01-01
      • 2022-10-21
      • 1970-01-01
      • 2023-03-26
      • 2014-12-09
      • 2016-04-26
      相关资源
      最近更新 更多