为什么注销导航链接不适用于 localStorage?

Why logout navlink doesn't work with localStorage?

我正在尝试使用 localStorage 以便 connect/disconnect 我网站上的用户。我试图通过点击导航栏的条件来管理这个(它涉及最新的 NavLink 组件)。在中间件中,我恢复了令牌(使用 console.log 验证)。当用户想要注销时,我想清空令牌并显示 "LogIn" 而不是 "LogOut" 。但这没有效果。单击时令牌确实为空,但无法断开连接。也无法再次连接,因为始终存在“注销”而未显示模态。非常感谢您的帮助! AppHeader (index.js)

// import Bootsrap-react's components
import {
  Container,
  Navbar,
  Nav,
  Modal,
  Button,
  Form,
} from 'react-bootstrap';
import { useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { LinkContainer } from 'react-router-bootstrap';
import logo from 'src/assets/images/logo.png';
import { fetchAllEvents } from '../../actions/events';
import { setSelectedRegionId } from '../../actions/regions';
import { setSelectedGenreId } from '../../actions/genres';
import { changeEmail, changePassword, logIn } from '../../actions/user';
import './appHeader.scss';

const AppHeader = () => {
  const dispatch = useDispatch();
  const [show, setShow] = useState(false);
  const emailValue = useSelector((state) => state.user.email);
  const passwordValue = useSelector((state) => state.user.password);
  const token = localStorage.getItem('token');

  const callLogin = () => {
    let isLogged;
    if (token !== null) {
      isLogged = 'Logout';
    }
    else {
      isLogged = 'Log In';
    }
    return isLogged;
  };
  const handleClose = () => setShow(false);
  const handleOpen = () => setShow(true);
  const logOut = () => localStorage.setItem('token', null);
  return (
    <div>
      <Navbar id="mainNav" expand="lg">
        <Container id="navbar-container">
          <LinkContainer to="/">
            <Navbar.Brand> <img src={logo} alt="logo" height="60" />
            </Navbar.Brand>
          </LinkContainer>
          <LinkContainer to="/">
            <Nav.Link>
              <h2 className="navbar-title">Concert'o</h2>
            </Nav.Link>
          </LinkContainer>
          <Navbar.Toggle aria-controls="basic-navbar-nav" />
          <Navbar.Collapse id="basic-navbar-nav " placement="right">
            <Nav className="flex-grow-1 justify-content-evenly">
              <LinkContainer
                to="/"
                onClick={() => {
                  dispatch(setSelectedGenreId());
                  dispatch(setSelectedRegionId());
                }}
              >
                <Nav.Link className="navlink-header">Accueil</Nav.Link>
              </LinkContainer>
              <LinkContainer to="/genres">
                <Nav.Link className="navlink-header">Genres</Nav.Link>
              </LinkContainer>
              <LinkContainer to="/regions">
                <Nav.Link className="navlink-header">Regions</Nav.Link>
              </LinkContainer>
              <LinkContainer
                to="/tous-les-evenements"
                onClick={() => {
                  dispatch(setSelectedGenreId());
                  dispatch(setSelectedRegionId());
                  dispatch(fetchAllEvents());
                }}
              >
                <Nav.Link className="navlink-header">Tous les événements</Nav.Link>
              </LinkContainer>
              <Nav.Link
                className="navlink-header "
                onClick={() => {
                  if (token !== null) {
                    dispatch(logOut());
                  }
                  else {
                    dispatch(handleOpen());
                  }
                }}
              >{callLogin()}
              </Nav.Link>
            </Nav>
          </Navbar.Collapse>
        </Container>
      </Navbar>
      <Modal show={show} onHide={handleClose}>
        <Modal.Header closeButton>
          <Modal.Title>Me connecter</Modal.Title>
        </Modal.Header>
        <Modal.Body>
          <Form>
            <Form.Group className="mb-3" controlId="exampleForm.ControlInput1">
              <Form.Label>Email</Form.Label>
              <Form.Control
                type="email"
                placeholder="name@example.com"
                autoFocus
                email={emailValue}
                onChange={(event) => {
                  // console.log(event.target.value);
                  dispatch(changeEmail(event.target.value));
                }}
              />
            </Form.Group>
            <Form.Group
              className="mb-3"
              controlId="exampleForm.ControlTextarea1"
            >
              <Form.Label>Mot de passe</Form.Label>
              <Form.Control
                type="password"
                password={passwordValue}
                onChange={(event) => {
                  // console.log(event.target.value);
                  dispatch(changePassword(event.target.value));
                }}

              />
            </Form.Group>
          </Form>
        </Modal.Body>
        <Modal.Footer>
          <Button
            variant="secondary"
            onClick={() => {
              dispatch(logIn());
              dispatch(handleClose());
            }}
          >
            Valider
          </Button>
          <LinkContainer
            to="/inscription"
          >
            <Button onClick={handleClose} variant="primary">
              Pas encore inscrit ? Cliquez ici
            </Button>
          </LinkContainer>
        </Modal.Footer>
      </Modal>
    </div>

  );
};
export default AppHeader;

用户缩减器

import { CHANGE_EMAIL, CHANGE_PASSWORD, SAVE_USER_DATA } from '../actions/user';

export const initialState = {

  email: '',
  password: '',
  username: '',
  token: null,
  errorMessage: '',
};

const user = (state = initialState, action = {}) => {
  switch (action.type) {
    case CHANGE_EMAIL:
      return {
        ...state,
        email: action.value,
      };
    case CHANGE_PASSWORD:
      return {
        ...state,
        password: action.value,
      };
    case SAVE_USER_DATA:
      return {
        ...state,
        username: action.nickname,
        token: action.token,
      };
    default:
      return state;
  }
};
export default user;

为什么 token 不是 null

You can only store a string in localStorage,因此当您将其设置为 null 并稍后检查值是否为 null 时,答案是否定的,因为 localStorage 现在等于字符串 "null",不是null.

您可以做的是完全删除令牌:

localStorage.removeItem("token");

然后简单地检查token是否存在:

let isLogged;
if (token) {
  isLogged = "Logout";
} else {
  isLogged = "Log In";
}
return isLogged;

您还可以使用以下代码缩短您的代码:

return token ? 'Logout' : 'Log In'

此外

您正在使用 dispatch,这是一个通过 传入操作对象 来更新 store 的函数,但是 dispatch(logOut());dispatch(handleOpen());dispatch(handleClose()); 没有传入对象,这些函数没有 return 任何东西。这意味着您可能(并且应该)因此 运行 出错,因为这是对 dispatch 函数的不当使用。

Read more about dispatch here.