Я пытаюсь создать компонент защищенного маршрута, используя firebase, у меня есть следующие настройки
import React, { Component } from 'react';
import { Route, Redirect } from 'react-router-dom';
import firebase from 'firebase';
firebase.initializeApp({
apiKey: 'xxxxxx',
authDomain: 'xxxxxx',
databaseURL: 'xxxxxx',
projectId: 'xxxxxx',
storageBucket: 'xxxxxx',
messagingSenderId: 'xxxxxx',
});
class ProtectedRoute extends Component {
componentWillMount() {}
render() {
const { component: Component, layout: Layout, redirect, auth: isAuthorized, ...rest } = this.props;
if (!this.props.hasOwnProperty('auth') && !this.props.hasOwnProperty('layout')) {
return <Route {...this.props} />;
}
const template = Layout ? (
<Layout>
<Component />
</Layout>
) : (
<Component />
);
if (!this.props.hasOwnProperty('auth') && this.props.hasOwnProperty('layout')) {
return <Route {...rest} component = {() => template} />;
}
if (isAuthorized) {
firebase.auth().onAuthStateChanged(user => {
if (!user) {
console.info(user)
return redirect ? <Redirect to = {{ pathname: redirect }} /> : <Route render = {() => <div>Unauthorized</div>} />;
}
})
}
return <Route {...rest} render = {() => template} />;
}
}
export default ProtectedRoute;
Мои маршруты настроены таким образом, что позволяет мне проходить, если маршрут должен быть частным или нет.
import Route from './containers/ProtectedRoute';
<Switch>
<Route exact path = "/" component = {LandingPage} />
<Route path = "/private" auth = {true} component = {PrivatePage} />
<Redirect to = "/" />
</Switch>
Я ожидал, что при посещении /private я должен вызвать вызов firebase.auth().onAuthStateChanged, а при возврате null я должен запустить логику перенаправления.
Вместо этого я все еще нажимаю return <Route {...rest} render = {() => template} />;
Между тем console.info в вызове firebase выдает null
firebase.auth().onAuthStateChanged является асинхронным, поэтому оператор return внутри вашего if (isAuthorized) { ... } никогда не используется при рендеринге, поэтому return <Route {...rest} render = {() => template} />; всегда будет запускаться в этом случае.
@Tholle подробности электронная почта e reg e audzieci e
Я думал, что, поскольку оператор return находится в обратном вызове onAuthStateChanged, он все равно будет работать?
Метод рендеринга является синхронным, поэтому, к сожалению, никакая асинхронная логика работать не будет.
Ах, я понимаю, спасибо, я по глупости подумал, что это асинхронно, поэтому я предполагаю, что мне следует переместить это в ловушку жизненного цикла и настроить поток другим способом?
Да, наверное, лучшее решение.



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


firebase.auth().onAuthStateChanged является асинхронным, поэтому оператор return внутри вашего if (isAuthorized) { ... } никогда не запускается.
Вместо этого вы можете поместить эту логику в componentDidMount и сохранить результат последнего изменения в вашем компоненте state и использовать его.
Пример
class ProtectedRoute extends Component {
auth = firebase.auth();
state = { user: this.auth.currentUser };
componentDidMount() {
this.unsubscribe = this.auth.onAuthStateChanged(user => {
this.setState({ user });
});
}
componentWillUnmount() {
this.unsubscribe();
}
render() {
const {
component: Component,
layout: Layout,
redirect,
auth: isAuthorized,
...rest
} = this.props;
const { user } = this.state;
if (
!this.props.hasOwnProperty("auth") &&
!this.props.hasOwnProperty("layout")
) {
return <Route {...this.props} />;
}
const template = Layout ? (
<Layout>
<Component />
</Layout>
) : (
<Component />
);
if (
!this.props.hasOwnProperty("auth") &&
this.props.hasOwnProperty("layout")
) {
return <Route {...rest} component = {() => template} />;
}
if (isAuthorized && !user) {
return redirect ? (
<Redirect to = {{ pathname: redirect }} />
) : (
<Route render = {() => <div>Unauthorized</div>} />
);
}
return <Route {...rest} render = {() => template} />;
}
}
Если я не ошибаюсь, вам всегда нужно сначала проверить
if (isAuthorized) {...}.