导航栏不会根据路由条件在 app.js 中呈现。路由更改时不会触发 Useeffect

Posted

技术标签:

【中文标题】导航栏不会根据路由条件在 app.js 中呈现。路由更改时不会触发 Useeffect【英文标题】:Navbar is not rendering in app.js based on routing condition. Useeffect is not getting triggered on route change 【发布时间】:2021-10-12 20:33:01 【问题描述】:

在此代码中,如果用户已登录(如果用户信息存储在本地存储中),我将根据条件使用导航栏,除了登录组件,我正在渲染导航栏组件。 但是在各自的组件中成功登录后,在第一次路由时,它没有在顶部显示导航栏,只有在我刷新页面时才会显示。 I tried this solution, But this solution didnt work for me 组件如下。 谢谢你

索引.js

    import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import 'bootstrap/dist/css/bootstrap.min.css';
import  BrowserRouter  from 'react-router-dom'
ReactDOM.render(
  <React.StrictMode>
    <BrowserRouter><App /></BrowserRouter>
  </React.StrictMode>,
  document.getElementById('root')
);
reportWebVitals();

App.js

import  React, useEffect,useState  from 'react'
import  BrowserRouter as Router, Switch, Route,withRouter  from 'react-router-dom'
import Login from './components/login/Login'
import Admin from './components/admin/Admin'
import ProtectedRoute from './ProtectedRoute'
import Navbar from './components/Navbar/Navbar'
const App = () => 
  const [nb, setNb] = useState(false)
  const checkIsAuth = () => 
    const _isAuth = localStorage.getItem('isAuth');
    const _user = localStorage.getItem('user');
    const _password = localStorage.getItem('password');
    if (_isAuth && _user && _password) setNb(true)
  
  useEffect(() => 
    checkIsAuth()
  , [])
  return (
    <div style= textAlign: "center" >
      nb && <Navbar />
        <Switch>
          <ProtectedRoute exact path=`/admin` component=Admin />
          <Route exact path="/" component=Login />
        </Switch>
    </div>
  );


export default withRouter(App);

登录.js

import  React, useEffect, useState  from 'react'
import  useHistory  from 'react-router-dom'
import  Form, Button  from 'react-bootstrap'
import  withRouter  from 'react-router-dom'
const Login = () => 
    const history = useHistory()
    const [userName, setUserName] = useState('')
    const [password, setPassword] = useState('')
    const submit = () => 
        if ((userName === 'admin' || userName === 'operator' || userName === 'supervisor') && password === 'welcome') 
            localStorage.setItem('user', userName)
            localStorage.setItem('isAuth', true)
            localStorage.setItem('password', password)
            setPassword('');
            setUserName('');
            history.push(`/$userName`)
        
        else if (!((userName === 'admin' || userName === 'operator' || userName === 'supervisor') && password === 'welcome')) 
            alert("Invalid Credentials")
            setPassword('')
            setUserName('')
            history.push(`/`)
        
    
    const checkIsAuth = () => 
        const _isAuth = localStorage.getItem('isAuth');
        const _user = localStorage.getItem('user');
        const _password = localStorage.getItem('password');
        if (_isAuth && _user && _password) history.push(`/$localStorage.getItem('user')`)
    
    useEffect(() => 
        checkIsAuth()
    , [])
    return (
        <div>
            <Form>
                <Form.Group className="mb-3" controlId="formBasicEmail">
                    <Form.Label>Username</Form.Label>
                    <Form.Control type="text" placeholder="Enter Username" onChange=e => setUserName(e.target.value)
                    />
                </Form.Group>
                <Form.Group className="mb-3" controlId="formBasicPassword">
                    <Form.Label>Password</Form.Label>
                    <Form.Control type="password" placeholder="Password" onChange=e => setPassword(e.target.value) />
                </Form.Group>
                <Button variant="primary" onClick=submit>
                    Submit
                </Button>
            </Form>
        </div>
    )


export default withRouter(Login)

ProtectedRoute.js

import React from 'react'
import  Route, Redirect  from 'react-router-dom'
const ProtectedRoute = ( component: Component, ...rest ) => 
    const checkIsAuth = () => 
        const _isAuth = localStorage.getItem('isAuth');
        const _user = localStorage.getItem('user');
        const _password = localStorage.getItem('password');
        let res =  isAuth: !!_isAuth, user: _user, password: _password 
        return res
    
    return (
        <Route ...rest
            render=(props) => 
                if (checkIsAuth().isAuth && checkIsAuth().user && checkIsAuth().password) 
                    return <Component />
                
                else 
                    return <Redirect to= pathname: '/', state:  from: props.location   />
                
            
        />
    )


export default ProtectedRoute

Admin.js

    import React from 'react'
import  withRouter  from 'react-router-dom'
const Admin = () => 
    return (
        <div>
            Admin
        </div>
    )


export default withRouter(Admin)

【问题讨论】:

您应该在App 中使用一些本地组件状态来保存身份验证状态并将状态/回调传递给路由呈现的子组件,或者使用 React 上下文或 redux 来保存全局应用程序状态。您应该从 localStorage 初始化状态,并且只将状态更新持久化回 localStorage。你的组件都在做太多的 localStorage 微管理。这里的问题是 App 仅在安装时检查 localStorage,这就是为什么需要重新加载页面才能从 localStorage 重新读取更新的值。 【参考方案1】:

需要更改

App.js

import  React, useEffect,useState  from 'react'
import  BrowserRouter as Router, Switch, Route,withRouter  from 'react-router-dom'
import Login from './components/login/Login'
import Admin from './components/admin/Admin'
import ProtectedRoute from './ProtectedRoute'
import Navbar from './components/Navbar/Navbar'
const App = () => 
  const [nb, setNb] = useState(false)
  const checkIsAuth = () => 
    const _isAuth = localStorage.getItem('isAuth');
    const _user = localStorage.getItem('user');
    const _password = localStorage.getItem('password');
    if (_isAuth && _user && _password) setNb(true)
  
  useEffect(() => 
    checkIsAuth()
  , [])
  return (
    <div style= textAlign: "center" >
      nb && <Navbar />
        <Switch>
          <ProtectedRoute exact path=`/admin` component=Admin />
          <Route exact path="/" render=(routerProps) => <Login setNb=setNb/> />
        </Switch>
    </div>
  );


export default withRouter(App);

登录.js

import  React, useEffect, useState  from 'react'
import  useHistory  from 'react-router-dom'
import  Form, Button  from 'react-bootstrap'
import  withRouter  from 'react-router-dom'
const Login = (setNb) => 
    const history = useHistory()
    const [userName, setUserName] = useState('')
    const [password, setPassword] = useState('')
    const submit = () => 
        if ((userName === 'admin' || userName === 'operator' || userName === 'supervisor') && password === 'welcome') 
            localStorage.setItem('user', userName)
            localStorage.setItem('isAuth', true)
            localStorage.setItem('password', password)
            setPassword('');
            setUserName('');
            history.push(`/$userName`); 
            setNb(true); 
        
        else if (!((userName === 'admin' || userName === 'operator' || userName === 'supervisor') && password === 'welcome')) 
            alert("Invalid Credentials")
            setPassword('')
            setUserName('')
            history.push(`/`)
        
    
    const checkIsAuth = () => 
        const _isAuth = localStorage.getItem('isAuth');
        const _user = localStorage.getItem('user');
        const _password = localStorage.getItem('password');
        if (_isAuth && _user && _password) history.push(`/$localStorage.getItem('user')`)
    
    useEffect(() => 
        checkIsAuth()
    , [])
    return (
        <div>
            <Form>
                <Form.Group className="mb-3" controlId="formBasicEmail">
                    <Form.Label>Username</Form.Label>
                    <Form.Control type="text" placeholder="Enter Username" onChange=e => setUserName(e.target.value)
                    />
                </Form.Group>
                <Form.Group className="mb-3" controlId="formBasicPassword">
                    <Form.Label>Password</Form.Label>
                    <Form.Control type="password" placeholder="Password" onChange=e => setPassword(e.target.value) />
                </Form.Group>
                <Button variant="primary" onClick=submit>
                    Submit
                </Button>
            </Form>
        </div>
    )


export default withRouter(Login)

【讨论】:

以上是关于导航栏不会根据路由条件在 app.js 中呈现。路由更改时不会触发 Useeffect的主要内容,如果未能解决你的问题,请参考以下文章

为啥不根据路由渲染组件?

React&Material UI-如何根据路线删除导航按钮/链接?

使用 React 路由器更轻松地通过侧边栏导航动态呈现组件

ReactJS Bootstrap 导航栏和路由不能一起工作

根据路由反应路由器导航栏

Bootstrap 4 导航栏无法在 IE11 中正确呈现