Контекст аутентификации, не позволяющий получить доступ к защищенным маршрутам после авторизации Firebase в веб-приложении React

#reactjs #firebase

#reactjs #firebase

Вопрос:

Я создаю веб-приложение React с помощью Firebase Auth, в котором я хочу защитить определенные маршруты в зависимости от того, подписан пользователь или нет.

Для этого я использую Context для создания AuthProvider / AuthContext, создавая «PrivateRoute» на основе этого контекста и независимо от того, вошел ли пользователь в систему, прежде чем обернуть защищенные маршруты во вновь созданный PrivateRoute в моем App.js .

Маршруты теперь защищены, и попытка получить к ним доступ перенаправляет меня на мою страницу входа.

Однако после входа в систему вход выполняется успешно, и токен генерируется и сохраняется в локальном хранилище. Однако доступ к защищенным маршрутам по-прежнему недоступен.

Я подозреваю, что это связано со структурой моего App.js файл, но не могу быть полностью уверен.

Вот мой код..

Auth.js

 import React, { useEffect, useState } from 'react'
import * as firebase from "firebase/app";
import "firebase/auth";
import "firebase/firestore";
import firebaseConfig from './firebaseConfig';

export const AuthContext  = React.createContext();

export function AuthProvider({ children }) {
    const  [currentUser, setCurrentUser] = useState(null);

    useEffect(() => {
        firebase.auth().onAuthStateChanged(setCurrentUser);
    }, []);

    return (
        <AuthContext.Provider
        value={{currentUser}}
        >
            {children}
        </AuthContext.Provider>
    )
}
  

PrivateRoute.js — запись в журнал консоли возвращает значение undefined…

     import React, { useContext } from 'react';
    import { Route, Redirect } from 'react-router-dom';
    import { AuthContext } from './Auth'
    
    export default function PrivateRoute({ component: RouteComponent, ...rest }) {
        let currentUser = useContext(AuthContext)
        console.log(currentUser)
        return (
            <Route
            {...rest}
            render={routeProps =>
            !!currentUser ? (
                <RouteComponent {...routeProps} currentUser={currentUser} />
            ) : (
                <Redirect to={'/sign-in'}/>
            )
            }
            />
        )
    }
  

App.js

 import React, { Component } from 'react';
import { BrowserRouter, Route, Switch } from 'react-router-dom';
import PrivateRoute from './PrivateRoute';
import './App.css';
import './nodes.css'
import * as firebase from "firebase/app";
import "firebase/auth";
import "firebase/firestore";
import firebaseConfig from './firebaseConfig';


import Homepage from './components/index/homepage';
import SignIn from './components/sign-in/sign-in';
import Dashboard from './components/dashboard/dashboard';

class App extends Component {

  render() {
    return (
      <div>

      <Switch>

      <PrivateRoute exact path="/dashboard" component={Dashboard} />
      <Route exact path="/" component={Homepage}  />
      <Route path="/sign-in" component={SignIn} />
      <Route path="/register" component={Register} />

      </Switch>

      </div>
    )
  }
}

export default App;
  

Index.js

 import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter, Route, Switch, Redirect } from 'react-router-dom';
import App from './App';


ReactDOM.render(
    <BrowserRouter>
      <App />
    </BrowserRouter>,
  document.getElementById('root')
);
  

Я не включил ни один из своих компонентов в этот вопрос, но если это поможет ответить на этот вопрос, я более чем рад добавить его.

Спасибо!

РЕДАКТИРОВАТЬ: мой компонент входа..

 class SignIn extends Component {
  constructor(props) {
    super(props)

    this.state = {
      email: "",
      password: ""
    }
  }

  onChange = (e) => {
        this.setState({ [e.target.name]: e.target.value})
    }

  onSubmit = (e) => {

    e.preventDefault()

    firebase.auth().signInWithEmailAndPassword(this.state.email, this.state.password)
      .then((response) => {

      let user = firebase.auth().currentUser

      if (user.emailVerified === false) {
        this.props.history.push("/sign-in")
        firebase.auth().signOut()
        alert("You need to verify your email first.")
      } else {
        this.props.history.push("/dashboard")
      }

      })
      .catch((error) => {
        var errorCode = error.code;
        var errorMessage = error.message;
        console.log(errorCode);
        console.log(errorMessage);
      });

  }

  render() {
    return (
      <section className="signin-section">
        <div className="signin-container">

          <form className="signin-form" onSubmit={this.onSubmit}>
            <label className="signin-form-label">Email</label>
            <input className="signin-form-input" type="email" name="email" onChange={this.onChange} value={this.state.email}/>
            <label className="signin-form-label">Password</label>
            <input className="signin-form-input" type="password" name="password" onChange={this.onChange} value={this.state.password} />
            <button className="signin-form-button" type="submit" name="button">Continue</button>
            <a className="signin-form-reset" href="reset">Forgotten your password?</a>
            <a className="signin-register-link" href="register">Not got an account? Sign up.</a>
          </form>
        </div>
      </section>
    )
  }
}

export default SignIn;
  

Мой

Комментарии:

1. Вы пытались console.log(currentUser) проверить, не является ли оно null или не определено? Можете ли вы показать свой логический код входа?

2. Спасибо за ответ. Я добавил консоль. войдите в мой файл PrivateRoute перед возвратом, и он возвращает undefined… Итак, предположим, что это отчасти проблема? Я также обновлю свой ответ с помощью компонента входа в систему.

3. Как вы используете свой AuthProvider ? Я вижу, что вы создаете и делитесь контекстом в своих AuthProvider дочерних элементах, но я не вижу никаких связанных дочерних элементов AuthProvider

4. Я предлагаю определить контекст на уровне приложения, чтобы вы могли получить доступ к своему контексту через все компоненты

5. Можете ли вы предоставить ответ, объясняющий это примерами? Я попытался добавить ‘AuthProvider’ в оба моих index.js и App.js , оборачивая мои компоненты в «AuthProvider», но это не работает. Выполняется «Аутентификация», и я могу получить доступ к своим маршрутам без входа в систему.