【问题标题】:React does not rerun App() function when switching routes切换路由时 React 不会重新运行 App() 函数
【发布时间】:2021-12-08 04:12:42
【问题描述】:

我有一个 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>
        </>
      );
    }
}

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

我之所以发生是因为(我猜)React 只是在路由之间切换,从 /login/* (/dashboard) 但它不会重新运行 App() 函数,因此它不能重做 @987654329 @测试。

我想如果我在进入仪表板时试图强制 React 重新加载页面(我试过 this answer)但它不起作用。

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

提前致谢。

【问题讨论】:

  • 如果使用类组件,则需要通过 useState 或 state 将变量更改为状态。 React 只会重新渲染真正改变的组件。如果变量发生变化并且您想要重新渲染引用那些您需要状态的组件。
  • @FeedThePiano 谢谢。不过,你能告诉我一个好方法吗?我创建了一个存储resultat 的状态,但我不知道如何在路由切换时更新该状态。
  • 抱歉,回答迟了。在您的情况下,您使用的是功能组件,因此需要按如下方式定义和更新状态:const [userInfo, setUserInfo] = useState({someData}); 使用 userInfo 访问数据,使用 setUserInfo 更新数据。使用 setUserInfo 方法更新它很重要。否则,不会触发重新渲染,否则更改状态是不干净的。你可以在这里阅读更多内容:reactjs.org/docs/hooks-state.html希望这会有所帮助
  • 感谢您的帮助,问题是即使我将userInfo置于一个状态,我的&lt;Login&gt;也没有更新它,所以我考虑使用react-redux并且它有效!

标签: reactjs react-router-dom


【解决方案1】:

感谢@FeedThePiano 的帮助,我终于搞定了。

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

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

-我创建了一个reducer,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 状态会及时更新,并且重定向不会出现问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-04-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-16
    相关资源
    最近更新 更多