在if块中反应不渲染组件

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在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.log(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} />;

与此同时,firebase调用中的console.log输出为null

答案

firebase.auth().onAuthStateChanged是异步的,所以if (isAuthorized) { ... }中的return语句永远不会运行。

您可以将此逻辑放在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块中反应不渲染组件的主要内容,如果未能解决你的问题,请参考以下文章

Vue中重新渲染组件的方法总结

避免在反应组件中无限重新渲染

使用反应路由器 4 不渲染反应组件

在 componentDidMount 之后反应不渲染组件

是否可以在反应渲染函数中返回空?

在 useQuery 后反应组件不重新渲染