首页 > 解决方案 > 切换路由时 React 不会重新运行 App() 函数

问题描述

我有一个 React/Node 应用程序,它让用户登录并被重定向到他的仪表板。我想要实现的是防止用户在未登录的情况下转到其他页面。我的 App.js 如下所示:

function App() {
  const userInfo = localStorage.getItem("userInfo");
  let resultat = JSON.parse(userInfo);

  if(resultat!==null){
    if(resultat.status==="ok"){
      return (
        <>
        <Router basename={process.env.PUBLIC_URL}>
          <Switch>
            <Route path='/' exact component={ Dashboard }>
            </Route>
            <Route path='/login' exact component={ Login }>
            </Route>
            <Route path='/dashboard' exact component={ Dashboard }>
            </Route>
            <Route path='/other_route' exact component={ OtherComponent }>
            </Route>
          </Switch>
        </Router>
        </>
      );
    } else {
      return(
        <>
        <Router basename={process.env.PUBLIC_URL}>
          <Switch>
            <Route path='/' exact component={ Login }>
            </Route>
            <Route path='/login' exact component={ Login }>
            </Route>
            <Route path='/*' exact>
              <>
                You are not logged in. To see this page please, log in.
              </>
            </Route>
          </Switch>
        </Router>
        </>
      );
    }
  } else {
      return(
        <>
        <Router basename={process.env.PUBLIC_URL}>
          <Switch>
            <Route path='/' exact component={ Login }>
            </Route>
            <Route path='/login' exact component={ Login }>
            </Route>
            <Route path='/*' exact>
              <>
                You are not logged in. To see this page please, log in.
              </>
            </Route>
          </Switch>
        </Router>
        </>
      );
    }
}

/dashboard如果登录过程成功,我的 Login.js 组件会将用户重定向到路径。问题是它仍然加载说要登录的页面。如果我重新加载页面,它会显示实际的仪表板。

我发生这种情况是因为(我猜)React 只是在路由之间切换,从/loginto /*( /dashboard) 但它不会重新运行该App()函数,因此它无法重做if(resultat!==null)测试。

我想如果我试图在进入仪表板时强制 React 重新加载页面(我试过这个答案)但它没有用。

有什么办法可以实现我想要做的吗?

提前致谢。

标签: reactjsreact-router-dom

解决方案


感谢@FeedThePiano 的帮助,我能够弄清楚。

问题是,即使我使用状态来存储userInfo状态,用户登录时也没有更新(因为登录过程发生在<Login/>组件中)。所以我需要找到一种方法来更新<Login/>组件的状态。

react-redux提供了一种方法来做到这一点,这就是我的做法:

-我创建了一个减速器,Reducers\signInReducer.js

const initialState= {
    isSignedIn: false
}

export default function signInReducer(state= initialState, action){
    switch(action.type){
        case "LOGIN":
            return{
                ...state,
                isSignedIn: true
            }
        case "LOGOUT":
            return{
                ...state,
                isSignedIn: false
            }
        default:
            return(state);
      }
}

-我曾经Reducers\index.js将它与我的其他减速器结合使用:

import { combineReducers } from "redux";
import otherReducer from "./path/to/other/reducer";
import signInReducer from "./signInReducer";

const allReducers = combineReducers({otherReducer, signInReducer});

export default allReducers;

- 然后在我的Login.js我添加:

import React, {useRef, useState} from 'react';
import { useDispatch } from 'react-redux';

export default function login(){
    const dispatch= useDispatch();
    //Code for the login process
    //Login is done..
    dispatch({
        type: "LOGIN"
    });
    //We can now redirect (safely)
    //Code for redirection
}

- 然后我只需要更新我的状态App.js

import {useState, useEffect} from 'react';
import { useSelector, useDispatch } from 'react-redux';
//import the components..
function App() {
    const [isUserLoggedIn, setUserLoggedIn]= useState(false);
    const [userInfo, setUserInfo]= useState(null);
    const isLogged= useSelector(state => state.signInReducer);
    useEffect(()=> {
        let info= localStorage.getItem("userInfo");
        let parsedInfo= JSON.parse(info);
        if(parsedInfo!== null){
            setUserInfo(parsedInfo.data);
        }
    },[]);

    useEffect(()=> {
        if(isLogged.isSignedIn){
            setUserLoggedIn(true);
        } else {
            setUserLoggedIn(false);
        }
    },[isLogged]);

    useEffect(()=> {
        if(userInfo!== null){
            setUserLoggedIn(true);
        } else {
            setUserLoggedIn(false);
        }
    }, [userInfo]);

    if(isUserLoggedIn){
        return (
            <>
            <Router basename={process.env.PUBLIC_URL}>
              <Switch>
                <Route path='/' exact component={ Dashboard }>
                </Route>
                <Route path='/login' exact component={ Login }>
                </Route>
                <Route path='/dashboard' exact component={ Dashboard }>
                </Route>
                <Route path='/other_route' exact component={ OtherComponent }>
                </Route>
              </Switch>
             </Router>
            </>
          );
    } else {
        return(
          <>
          <Router basename={process.env.PUBLIC_URL}>
            <Switch>
              <Route path='/' exact component={ Login }>
              </Route>
              <Route path='/login' exact component={ Login }>
              </Route>
              <Route path='/*' exact>
                <>
                  You are not logged in. To see this page please, log in.
                </>
              </Route>
            </Switch>
          </Router>
          </>
        );
    }
}

这样,userInfo状态会按时更新,并且重定向没有问题。


推荐阅读