[英]What is the correct way to change Navbar values in React based on if user is logged in?
I'm new to React and I'm trying to understand how to do things in the right way.我是 React 的新手,我正在努力了解如何以正确的方式做事。 So I have a Navbar that displays different links based on if a user is logged in or not.所以我有一个导航栏,它根据用户是否登录显示不同的链接。 If a user logs in i set a cookie loggedIn=true
.如果用户登录,我会设置一个 cookie 登录loggedIn=true
。 Than in my Navbar component, I check for these cookies with window.setInterval
:比在我的 Navbar 组件中,我使用window.setInterval
检查这些 cookie:
import React, { Component } from 'react'
import { NavLink, Link } from "react-router-dom"
import styles from './Navbar.module.css'
class Navbar extends Component {
constructor() {
super()
this.state = {
loggedIn: false
}
}
componentDidMount() {
if (document.cookie.split(';').filter((item) => item.trim().startsWith('logedIn=')).length) {
this.setState({ loggedIn: true })
}
window.setInterval(() => {
if (document.cookie.split(';').filter((item) => item.trim().startsWith('logedIn=')).length) {
this.setState({ loggedIn: true })
}
else {
this.setState({ loggedIn: false })
}
}, 500)
}
render() {
return (
<header>
<nav className={` ${styles.navbar} navbar navbar-dark bg-dark navbar-expand-lg`}>
<div className='container'>
<Link className='navbar-brand mr-5' to='/'>I <i className={`${styles.red} fas fa-heart fa-xs`}></i> Jokes</Link>
<button className="navbar-toggler"
type="button"
data-toggle="collapse"
data-target="#navbarContent"
aria-controls="navbarContent"
aria-expanded="false"
aria-label="Toggle navigation">
<span className="navbar-toggler-icon"></span>
</button>
<div className="collapse navbar-collapse" id="navbarContent">
<ul className="navbar-nav mr-auto">
<li className="nav-item ">
<NavLink className="nav-link" exact to="/">Home</NavLink>
</li>
<li className="nav-item">
<NavLink className="nav-link" to="/about">About</NavLink>
</li>
</ul>
<ul className="navbar-nav">
{this.state.loggedIn ?
<React.Fragment>
<NavLink className="nav-link mr-3" to="/myaccount">My account</NavLink>
<NavLink className='nav-link' to='/logout'>Log out</NavLink>
</React.Fragment>
:
<React.Fragment>
<NavLink className='nav-link mr-3 ' to='/login'>Log in</NavLink>
<NavLink className='nav-link' to='/signup'>Sign up</NavLink>
</React.Fragment>
}
</ul>
</div>
</div>
</nav>
</header>
)
}
}
export default Navbar
Here is my App component:这是我的应用程序组件:
import React from 'react'
import { Route, Switch } from 'react-router-dom'
import Navbar from './components/Navbar/Navbar'
import Footer from './components/Footer/Footer'
import Home from './components/Home/Home'
import About from './components/About/About'
import SignUp from './components/SignUp/SignUp'
import LogIn from './components/LogIn/LogIn'
import UserAccount from './components/UserAccount/UserAccount'
import './App.css'
function App() {
return (
<div className="App">
<Navbar />
<Switch>
<Route exact path='/about' component={About} />
<Route exact path='/signup' component={SignUp} />
<Route exact path='/login' component={LogIn} />
<Route exact path='/account' component={UserAccount}/>
<Route exact path='/' component={Home} />
</Switch>
<Footer />
</div>
);
}
export default App;
I feel like it's a wrong way to do it, and I'd like to get pointers on how to do it properly.我觉得这是一种错误的方法,我想获得有关如何正确执行的指示。 Thanks!谢谢!
I would recommend Lifting State Up in this case:在这种情况下,我建议提升状态:
function App() {
const [loggedIn, setLoggedIn] = useState(
// initial value
document.cookie.split(';').some((item) => item.trim().startsWith('logedIn=')));
return (
<div className="App">
<Navbar {...{loggedIn}} />
<Switch>
<Route exact path='/about' component={About} />
<Route exact path='/signup' component={SignUp} />
<Route exact path='/login' render={
(routeProps) => <LogIn {...{setLoggedIn, ...routeProps}} />
} />
<Route exact path='/account' component={UserAccount}/>
<Route exact path='/' component={Home} />
</Switch>
<Footer />
</div>
);
}
and use the additional props in Navbar
and LogIn
components (cookies only used when reloading the page for the initial state above, not inside Navbar):并在Navbar
和LogIn
组件中使用额外的道具(cookies 仅在为上述初始状态重新加载页面时使用,而不是在 Navbar 内):
fucntion Navbar(props) {
return (
<header>
...
{props.loggedIn ? ... // instead of this.state.loggedIn
)
}
render() { const link1 = this.state.loggedIn ? '/myaccount' : '/login'; const link1 = this.state.loggedIn ? '/logout' : '/signup'; return ( ... <ul className="navbar-nav"> <NavLink className="nav-link mr-3" to={link1}>My account</NavLink> <NavLink className='nav-link' to={link2}>Log out</NavLink> </ul> ) }
您不应该复制大量代码,因为您相信可以像这样以更好的方式更改链接: render() { const link1 = this.state.loggedIn ? '/myaccount' : '/login'; const link1 = this.state.loggedIn ? '/logout' : '/signup'; return ( ... <ul className="navbar-nav"> <NavLink className="nav-link mr-3" to={link1}>My account</NavLink> <NavLink className='nav-link' to={link2}>Log out</NavLink> </ul> ) }
render() { const link1 = this.state.loggedIn ? '/myaccount' : '/login'; const link1 = this.state.loggedIn ? '/logout' : '/signup'; return ( ... <ul className="navbar-nav"> <NavLink className="nav-link mr-3" to={link1}>My account</NavLink> <NavLink className='nav-link' to={link2}>Log out</NavLink> </ul> ) }
Checking whether a user is logged in is probably out of the scope of this question, but you seem to be handling it anyway.检查用户是否登录可能超出了此问题的范围,但您似乎仍在处理它。
As you cannot use if statements in JSX, the two accepted ways to conditionally render JSX based on certain values is either via a ternary operator or a switch statement if you have multiple conditions to check against.由于您不能在 JSX 中使用 if 语句,因此根据某些值有条件地呈现 JSX 的两种公认方法是通过三元运算符或 switch 语句(如果您有多个条件要检查)。
An example of using a ternary operator would be when you need to render a different navbar based on whether a user is logged in or not.使用三元运算符的一个示例是,您需要根据用户是否登录来呈现不同的导航栏。
An example of when you would use a switch statement would be when you had multiple user roles and each of them needed to see a different iteration of a navbar.何时使用 switch 语句的一个示例是当您有多个用户角色并且每个角色都需要查看导航栏的不同迭代时。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.