Реагировать, не отображая компонент в блоке if

Я пытаюсь создать компонент защищенного маршрута, используя 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

Если я не ошибаюсь, вам всегда нужно сначала проверить if (isAuthorized) {...}.

Ason 07.07.2018 12:45
firebase.auth().onAuthStateChanged является асинхронным, поэтому оператор return внутри вашего if (isAuthorized) { ... } никогда не используется при рендеринге, поэтому return <Route {...rest} render = {() => template} />; всегда будет запускаться в этом случае.
Tholle 07.07.2018 12:47

@Tholle подробности электронная почта e reg e audzieci e

BartZalas 07.07.2018 12:52

Я думал, что, поскольку оператор return находится в обратном вызове onAuthStateChanged, он все равно будет работать?

Harry Blue 07.07.2018 12:52

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

Tholle 07.07.2018 12:53

Ах, я понимаю, спасибо, я по глупости подумал, что это асинхронно, поэтому я предполагаю, что мне следует переместить это в ловушку жизненного цикла и настроить поток другим способом?

Harry Blue 07.07.2018 12:55

Да, наверное, лучшее решение.

Tholle 07.07.2018 12:59
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
3
7
65
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

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} />;
  }
}

Другие вопросы по теме