#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», но это не работает. Выполняется «Аутентификация», и я могу получить доступ к своим маршрутам без входа в систему.