最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - What is the correct way to change Navbar values in React based on if user is logged in? - Stack Overflow

programmeradmin0浏览0评论

I'm new to React and I'm trying to understand how to do things in the right way. 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. Than in my Navbar ponent, I check for these cookies with window.setInterval:

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
    }
  }

  ponentDidMount() {
    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 ponent:

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

import Navbar from './ponents/Navbar/Navbar'
import Footer from './ponents/Footer/Footer'
import Home from './ponents/Home/Home'
import About from './ponents/About/About'
import SignUp from './ponents/SignUp/SignUp'
import LogIn from './ponents/LogIn/LogIn'
import UserAccount from './ponents/UserAccount/UserAccount'
import './App.css'

function App() {
  return (
    <div className="App">
      <Navbar />
      <Switch>
        <Route exact path='/about' ponent={About} />
        <Route exact path='/signup' ponent={SignUp} />
        <Route exact path='/login' ponent={LogIn} />
        <Route exact path='/account' ponent={UserAccount}/>
        <Route exact path='/' ponent={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'm new to React and I'm trying to understand how to do things in the right way. 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. Than in my Navbar ponent, I check for these cookies with window.setInterval:

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
    }
  }

  ponentDidMount() {
    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 ponent:

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

import Navbar from './ponents/Navbar/Navbar'
import Footer from './ponents/Footer/Footer'
import Home from './ponents/Home/Home'
import About from './ponents/About/About'
import SignUp from './ponents/SignUp/SignUp'
import LogIn from './ponents/LogIn/LogIn'
import UserAccount from './ponents/UserAccount/UserAccount'
import './App.css'

function App() {
  return (
    <div className="App">
      <Navbar />
      <Switch>
        <Route exact path='/about' ponent={About} />
        <Route exact path='/signup' ponent={SignUp} />
        <Route exact path='/login' ponent={LogIn} />
        <Route exact path='/account' ponent={UserAccount}/>
        <Route exact path='/' ponent={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!

Share Improve this question edited Jul 27, 2019 at 14:33 Shubham Verma 5,0541 gold badge10 silver badges22 bronze badges asked Jul 27, 2019 at 14:16 NoobNoob 2,8074 gold badges23 silver badges43 bronze badges 2
  • 2 Maybe this help : kentcdodds./blog/authentication-in-react-applications – Shubham Verma Commented Jul 27, 2019 at 14:29
  • 1 small hint '<React.Fragment></React.Fragment>' can be used via shortcut '<></>' link to react docs – Oleg Lozynskyi Commented Jul 27, 2019 at 14:33
Add a ment  | 

3 Answers 3

Reset to default 3

I would remend 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' ponent={About} />
        <Route exact path='/signup' ponent={SignUp} />
        <Route exact path='/login' render={
          (routeProps) => <LogIn {...{setLoggedIn, ...routeProps}} />
        } />
        <Route exact path='/account' ponent={UserAccount}/>
        <Route exact path='/' ponent={Home} />
      </Switch>
      <Footer />
    </div>
  );
}

and use the additional props in Navbar and LogIn ponents (cookies only used when reloading the page for the initial state above, not inside Navbar):

fucntion Navbar(props) {
  return (
    <header>
      ...
      {props.loggedIn ? ... // instead of this.state.loggedIn
  )
}
  1. You shouldn't duplicate a lot of code a believe you can change the links in a better way like this: 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> ) }
  2. Not fully understand why you check if user logged in through cookies, maybe there is better option as JWT autorization ? here is a link

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.

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.

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论