简体   繁体   English

当用户登录时,如何更改此导航栏下拉项以从“登录”更新为“注销”?

[英]How can I change this Navbar dropdown item to update from "Login" to "Logout" when a user logs in?

I am trying to update my Navbar component so that when a user logs in, the navbar dropdown item "Login" changes to "Logout" but I am having issues.我正在尝试更新我的Navbar组件,以便当用户登录时,导航栏下拉项“登录”更改为“注销”,但我遇到了问题。 I am new to react and JS but learning as I go, so I apologize for any confusion in this question.我是 React 和 JS 的新手,但作为我 go 学习,所以对于这个问题中的任何混淆,我深表歉意。 I have jsx components for my Navbar , Dropdown , Footer , and for each page that a user wants to view which is rendered in my App.js file.我的NavbarDropdownFooter以及用户想要查看的每个页面都有 jsx 组件,这些页面在我的App.js文件中呈现。

Navbar.jsx:导航栏.jsx:

import React, {useState, useEffect} from 'react';
import {Link} from 'react-router-dom'; 
import './Navbar.css';
import Dropdown from './Dropdown';
import {NavItemsList} from './NavItemsList';
import NavItems from './NavItems';

function Navbar() {
    const [click, setClick] = useState(false); 
    const [button, setButton] = useState(true);
    const [dropdown, setDropdown] = useState(false);

    const handleClick = () => setClick(!click);
    const closeMobileMenu = () => setClick(false);

    const onMouseEnter = () => {
        if (window.innerWidth < 960) {
            setDropdown(false);
        } else {
            setDropdown(true);
        }
    };

    const onMouseLeave = () => {
        if (window.innerWidth < 960) {
            setDropdown(false);
        } else {
            setDropdown(false);
        }
    };

    return (
        <>
            <nav className='navbar'>
                <div className='navbar-container-whole'>
                    <div className='left-nav-container'>
                        {/* Link in react-router-dom essentially replaces a tag.*/}
                        <Link to='/' className='navbar-logo'>
                            <img src='/images/logo.png' className='hashtek-logo' alt='logo' />
                            <h1 className='navbar-name'>HashTek</h1>
                        </Link>
                    </div>
                    {/* .navbar-container will create a div with that class name. */}
                    <div className='center-nav-container'>
                        <form action='./' method='get' id='search-form'>
                            <div class='searchbar'>
                                <input
                                    class='searchbar_input'
                                    type='search'
                                    name='search'
                                    placeholder='Search..'
                                />

                                <button type='submit' class='searchbar_button'>
                                    <i class='material-icons'>search</i>
                                </button>
                            </div>
                        </form>
                    </div>
                    <div className='right-nav-container'>
                        <ul className={click ? 'nav-menu active' : 'nav-menu'}>
                            <div className='text-links'>
                                {/* This line above is for when you are on mobile, and an item is clicked, the nav menu will disappear */}
                                {NavItemsList.slice(0, 4).map((menu, index) => {
                                    return <NavItems items={menu} key={index} />;
                                })}
                            </div>
                            <div className='logo-links'>
                                {NavItemsList.slice(4, 6).map((menu, index) => {
                                    return <NavItems items={menu} key={index} />;
                                })}
                            </div>
                        </ul>
                        <div className='menu-icon' onClick={handleClick}>
                            <i className={click ? 'fas fa-times' : 'fas fa-bars'} />
                        </div>
                    </div>
                </div>
            </nav>
        </>
    );
}

export default Navbar;

NavItemsList.js: NavItemsList.js:

export const NavItemsList = [
    {
        title: 'Products',
        path: '/products',
        cName: 'nav-links',
    },
    {
        title: 'Stats',
        path: '/stats',
        cName: 'nav-links',
    },
    {
        title: 'Contacts',
        path: '/contacts',
        cName: 'nav-links',
        subNav: [
            {
                title: 'About',
                path: '/contacts/about',
                cName: 'dropdown-link',
                menuName: 'contacts-menu',
            },
            {
                title: 'How To',
                path: '/contacts/how-to',
                cName: 'dropdown-link',
                menuName: 'contacts-menu',
            },
            {
                title: 'Developers',
                path: '/contacts/developers',
                cName: 'dropdown-link',
                menuName: 'contacts-menu',
            },
            {
                title: 'Designers',
                path: '/contacts/designers',
                cName: 'dropdown-link',
                menuName: 'contacts-menu',
            },
            {
                title: 'Mentors',
                path: '/contacts/mentors',
                cName: 'dropdown-link',
                menuName: 'contacts-menu',
            },
        ],
    },
    {
        title: 'Services',
        path: '/services',
        cName: 'nav-links',
        subNav: [
            {
                title: 'Streaming',
                path: '/services/streaming',
                cName: 'dropdown-link',
                menuName: 'services-menu',
            },
            {
                title: 'Editing',
                path: '/services/editing',
                cName: 'dropdown-link',
                menuName: 'services-menu',
            },
        ],
    },
    {
        title: Account,
        path: '/my-account',
        cName: 'nav-links',
        subNav: [
            {
                title: 'Login',
                path: '/login',
                cName: 'dropdown-link',
                menuName: 'account-menu',
            },
            {
                title: 'Profile',
                path: '/profile',
                cName: 'dropdown-link',
                menuName: 'account-menu',
            },
        ],
    },
    {
        title: Help,
        path: '/help',
        cName: 'nav-links',
    },
];

Dropdown.jsx:下拉.jsx:

import React, {useState} from 'react';
import {Link} from 'react-router-dom';
import './Dropdown.css';

function Dropdown(props) {
    const [click, setClick] = useState(false);
    const handleClick = () => setClick(!click);
    const submenus = props.submenus;

    return (
        <ul
            onClick={handleClick}
            className={click ? 'dropdown-menu clicked' : 'dropdown-menu'}
        >
            {submenus.map((subNav, index) => (
                <div className={subNav.menuName}>
                    <li key={index} className='dropdown-links'>
                        <Link
                            className={subNav.cName}
                            to={subNav.path}
                            onClick={() => setClick(false)}
                        >
                            {subNav.title}
                        </Link>
                    </li>
                </div>
            ))}
        </ul>
    );
}

export default Dropdown;

NavItems.jsx:导航项.jsx:

import React, {useState} from 'react';
import Dropdown from './Dropdown';
import {Link} from 'react-router-dom';

function NavItems(props) {
    const items = props.items;
    const [click, setClick] = useState(false);
    const handleClick = () => setClick(!click);
    const [dropdown, setDropdown] = useState(false);

    const onMouseEnter = () => {
        if (window.innerWidth < 960) {
            setDropdown(false);
        } else {
            setDropdown(true);
        }
    };

    const onMouseLeave = () => {
        if (window.innerWidth < 960) {
            setDropdown(false);
        } else {
            setDropdown(false);
        }
    };

    return (
        <div className='link-container' onMouseLeave={onMouseLeave}>
            <li className='nav-item'>
                {items.subNav ? (
                    <>
                        <Link
                            className={items.cName}
                            to={items.path}
                            onClick={() => setClick(false)}
                            onMouseEnter={onMouseEnter}
                        >
                            {items.title}
                        </Link>

                        {dropdown && <Dropdown submenus={items.subNav} />}
                    </>
                ) : (
                    <Link
                        className={items.cName}
                        to={items.path}
                        onClick={() => setClick(false)}
                    >
                        {items.title}
                    </Link>
                )}
            </li>
        </div>
    );
}

export default NavItems;

I am following a tutorial that implements the navbar in their App.js file as follows:我正在关注一个在其 App.js 文件中实现导航栏的教程,如下所示:

import React, { useState, useEffect, useCallback } from "react";
import { useDispatch, useSelector } from "react-redux";
import { BrowserRouter as Router, Switch, Route, Link } from "react-router-dom";
import "bootstrap/dist/css/bootstrap.min.css";
import "./App.css";
import Login from "./components/Login";
import Register from "./components/Register";
import Home from "./components/Home";
import Profile from "./components/Profile";
import BoardUser from "./components/BoardUser";
import BoardModerator from "./components/BoardModerator";
import BoardAdmin from "./components/BoardAdmin";
import { logout } from "./slices/auth";
import EventBus from "./common/EventBus";
const App = () => {
  const [showModeratorBoard, setShowModeratorBoard] = useState(false);
  const [showAdminBoard, setShowAdminBoard] = useState(false);
  const { user: currentUser } = useSelector((state) => state.auth);
  const dispatch = useDispatch();
  const logOut = useCallback(() => {
    dispatch(logout());
  }, [dispatch]);
  useEffect(() => {
    if (currentUser) {
      setShowModeratorBoard(currentUser.roles.includes("ROLE_MODERATOR"));
      setShowAdminBoard(currentUser.roles.includes("ROLE_ADMIN"));
    } else {
      setShowModeratorBoard(false);
      setShowAdminBoard(false);
    }
    EventBus.on("logout", () => {
      logOut();
    });
    return () => {
      EventBus.remove("logout");
    };
  }, [currentUser, logOut]);
  return (
    <Router>
      <div>
        <nav className="navbar navbar-expand navbar-dark bg-dark">
          <Link to={"/"} className="navbar-brand">
            bezKoder
          </Link>
          <div className="navbar-nav mr-auto">
            <li className="nav-item">
              <Link to={"/home"} className="nav-link">
                Home
              </Link>
            </li>
            {showModeratorBoard && (
              <li className="nav-item">
                <Link to={"/mod"} className="nav-link">
                  Moderator Board
                </Link>
              </li>
            )}
            {showAdminBoard && (
              <li className="nav-item">
                <Link to={"/admin"} className="nav-link">
                  Admin Board
                </Link>
              </li>
            )}
            {currentUser && (
              <li className="nav-item">
                <Link to={"/user"} className="nav-link">
                  User
                </Link>
              </li>
            )}
          </div>
          {currentUser ? (
            <div className="navbar-nav ml-auto">
              <li className="nav-item">
                <Link to={"/profile"} className="nav-link">
                  {currentUser.username}
                </Link>
              </li>
              <li className="nav-item">
                //INTERESTED IN THIS
                <a href="/login" className="nav-link" onClick={logOut}> 
                </a>
              </li>
            </div>
          ) : (
            <div className="navbar-nav ml-auto">
              <li className="nav-item">
                <Link to={"/login"} className="nav-link">
                  Login
                </Link>
              </li>
              <li className="nav-item">
                <Link to={"/register"} className="nav-link">
                  Sign Up
                </Link>
              </li>
            </div>
          )}
        </nav>
        <div className="container mt-3">
          <Switch>
            <Route exact path={["/", "/home"]} component={Home} />
            <Route exact path="/login" component={Login} />
            <Route exact path="/register" component={Register} />
            <Route exact path="/profile" component={Profile} />
            <Route path="/user" component={BoardUser} />
            <Route path="/mod" component={BoardModerator} />
            <Route path="/admin" component={BoardAdmin} />
          </Switch>
        </div>
      </div>
    </Router>
  );
};
export default App;

From what I can tell, they are checking the state of the currentUser and if there is one, then the Navbar will be updated to display LogOut and the current user's username.据我所知,他们正在检查currentUserNavbar ,如果有,则导航栏将更新以显示注销和当前用户的用户名。 This is where I am having trouble, since I have decided to import an array into my Navbar instead.这是我遇到麻烦的地方,因为我决定改为将数组导入我的Navbar Do I need to change my Navbar so that it renders the items in the Navbar component directly without the use of the NavItemsList , or is there a way for me to check the state and change "Login" to "Logout" without changing my NavItemsList component too much?我是否需要更改Navbar以便它在不使用NavItemsList的情况下直接呈现Navbar组件中的项目,或者我是否可以检查 state 并将“登录”更改为“注销”而不更改我的NavItemsList组件太多了? Any help would be appreciated, I have been scratching my head on how to go about this without refactoring my hard work.任何帮助将不胜感激,我一直在摸索如何在不重构我的辛勤工作的情况下解决这个问题 go。

I suggest you should add an "auth status" property to your links and routing configs so as you are mapping them into the UI you can check the current authentication status and render the appropriate content.我建议您应该在链接和路由配置中添加一个“身份验证状态”属性,以便在将它们映射到 UI 时可以检查当前的身份验证状态并呈现适当的内容。

Example:例子:

export const NavItemsList = [
    ...
    {
        title: Account,
        path: '/my-account',
        cName: 'nav-links',
        subNav: [
            {
                title: 'Login',
                path: '/login',
                cName: 'dropdown-link',
                menuName: 'account-menu',
                authenticated: false,
            },
            {
                title: 'Logout',
                path: '/logout',
                cName: 'dropdown-link',
                menuName: 'account-menu',
                authenticated: true,
            },
            {
                title: 'Profile',
                path: '/profile',
                cName: 'dropdown-link',
                menuName: 'account-menu',
            },
        ],
    },
    ...
];

... ...

function Dropdown({ submenus }) {
  const { user: currentUser } = useSelector((state) => state.auth);

  const [click, setClick] = useState(false);

  const handleClick = () => setClick(click => !click);

  return (
    <ul
      onClick={handleClick}
      className={click ? 'dropdown-menu clicked' : 'dropdown-menu'}
    >
      {submenus
        .filter(({ authenticated }) => {
          if (authenticated !== undefined) {
            return !!currentUser === authenticated;
          }
          return true;
        })
        .map((subNav) => (
          <div key={subNav.path} className={subNav.menuName}>
            <li className='dropdown-links'>
              <Link
                className={subNav.cName}
                to={subNav.path}
                onClick={() => setClick(false)}
              >
                {subNav.title}
              </Link>
            </li>
          </div>
        ))
      }
    </ul>
  );
}

I would Ideally do something like this in the NavItem我最好在 NavItem 中做这样的事情

{subNav.title==='Login'?(userLoggedIn?'Logout':'Login'):subNav.title}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM