必须刷新才能根据自定义声明更改导航(ReactJS 和 Firebase 自定义声明)

Having to refresh to change navigation based on custom claim (ReactJS and Firebase Custom Claims)

我目前正在从事一个涉及 Firebase 自定义声明的项目,他们需要管理员和用户角色。 我现在已经开始工作了。

当用户以管理员身份登录时,显示管理员导航栏,当他们只是用户时,显示用户导航栏。

但是,在用户刷新页面之前,我的导航不会改变。

解决这个问题的最佳方法是什么?

Header.js

import React, { Component } from 'react';
import {Link} from 'react-router-dom';
import './Header.scss';
import PublicNavigation from '../PublicLinks/PublicLinks';
import AdminNavigation from '../AdminLinks/AdminLinks';
import UserNavigation from '../UserLinks/UserLinks';
import SignUpButton from '../SignUpButton/SignUpButton';
import { connect } from 'react-redux';
import LogOut from '../LogOut/LogOut';



const firebase = require("firebase");

const Header = (props) => {
    // Firebase Login Check -- This is what changes the navigation based on whether the user is logged in or not!
    const { auth } = props;
    // console.log(auth);
    // const nav = auth.uid ? <UserNavigation/> : <PublicNavigation/> 
    const button = auth.uid ? <LogOut/> : <SignUpButton/>
    
    return (
      <div className = "Header">
          
            <div className = "Logo">
                {/* Company Logo */}
                <h1 className = "CompanyName"> Logo.</h1>
            </div>

            {/* These are the login , signup and log out buttons */}
            { button }

            <div className = "Navigation"> 

            <Nav auth={ auth }/>

            </div>
        
           

            
        </div>
    )
}

const mapStateToProps = (state) => {
    return {
        auth: state.firebase.auth
    }
}


class Nav extends Component {
   state = {
      navType: 'public'
    }

    componentDidMount(){
        if (firebase.auth().currentUser == null) {
            console.log('public')
            this.setState({ navType: "public" }) 
          } else {
            firebase.auth().currentUser.getIdTokenResult()
             .then ((IdTokenResult) => {
                 console.log(IdTokenResult);
               if (!!IdTokenResult.claims.admin){
                this.setState({ navType: "admin" }) 
               } else {
                  this.props.auth.uid ? this.setState({ navType: "user" })  :  this.setState({ navType: "public" }) 
               }
            });
          }
    }
  
    
    render() {
        let nav = null;
        if (this.state.navType === "admin")
           nav = <AdminNavigation/>
                      else if(this.state.navType  === "user")
                      nav = <UserNavigation/>
                      else
                      nav = <PublicNavigation/> 
        return (
          <div>
            {nav}
          </div>
         );
      }
    }

export default connect(mapStateToProps)(Header)

App.js

import React from 'react';
import { BrowserRouter, Switch, Route} from 'react-router-dom';

// Layout Components 
import Header from './components/Layout/Header/Header';
import Footer from './components/Layout/Footer/Footer';

// Public Access Pages
import PublicIndex from './components/Public/Index/Index';
import About from './components/Public/About/About';
import FAQ from './components/Public/FAQ/FAQ';
import Contact from './components/Public/Contact/Contact';

// Admin Access Pages


// User Access Pages

import CoursePortal from './components/User/CoursePortal/CoursePortal';
import LiveLessons from './components/User/LiveLessons/LiveLessons';

//Authentication Pages
import Login from './components/Auth/Login/Login';
import SignUp from './components/Auth/SignUp/SignUp';

function App() {
  
  return (
    <BrowserRouter>
    <div className="App">
    <Header/>
    <Switch>
        {/* path = the end of the URL || component = the page of which will be shown, as imported above */}

         {/* ADMIN ONLY PAGES */}
         


        {/* LOGGED IN USER ACCESS PAGES */}
        <Route exact path = '/livelessons' component = {LiveLessons} />
        <Route exact path = '/courseportal' component = {CoursePortal}/>

        {/* AUTHENTICATION PAGES */}
        <Route exact path ='/login' component = {Login}/>
        <Route exact path ='/signup' component = {SignUp}/>

        {/* PUBLIC ACCESS PAGES */}
        <Route exact path = '/contact' component = {Contact} />
        <Route exact path = '/FAQ' component = {FAQ} />
        <Route exact path = '/about' component = {About} />
        <Route exact path = '/' component = {PublicIndex} />
        

       
        
        
    </Switch>
    <Footer/>
    </div>
    </BrowserRouter>
  );
}

export default App;

听起来您的 Nav 组件没有在身份验证状态更改时更新。您将需要监听组件中的身份验证状态:

// in component Nav
componentDidMount() {
    this.authListener = firebase.auth().onAuthStateChanged(user => {
        if (!user) {
            this.setState({ navType: "public" });
        } else {
            user.getIdTokenResult().then(IdTokenResult => {
                if (!!IdTokenResult.claims.admin) {
                    this.setState({ navType: "admin" });
                } else {
                    this.setState({ navType: "user" });
                }
            });
        }
    });
}

componentWillUnmount() {
    // Do not forget to stop listening to the auth state when unmounting
    if (this.authListener) {
        this.authListener();
    }
}

这样,当 auth 状态发生变化时,Nav 组件将自动更新其 navType 状态,然后 re-render 具有正确的权限。