如何在不使用 Redux 的情况下显示隐藏基于身份验证的注销按钮?

How can I show hide my logout button based on authentication without using Redux?

使用下面的代码,只有当我在成功登录后刷新页面时,注销按钮才会显示。该功能按预期工作,所以没有问题。

此外,我想在用户成功登录 而不 刷新页面时在导航栏上显示注销按钮。

我尝试了很多方法来解决这个问题,但都无济于事。

在我的研究过程中,我遇到了一个叫做 Redux Persist 的东西,但我不确定在这种情况下是否值得使用它。有没有一种方法可以在不使用 Redux 的情况下处理这个问题?

我愿意编写我的代码 improvements/suggestions。提前致谢。

import { Navbar, Nav, Container, Button } from 'react-bootstrap';
import axios from 'axios';
import { useHistory } from 'react-router-dom';
import {useEffect, useState} from "react";

const NavBar = () => {

    let history = useHistory();
    const [loggedInUser, setLoggedInUser] = useState("");

    useEffect(() => {
        const loggedInUser = localStorage.getItem("loginToken");
        console.log(loggedInUser);
        setLoggedInUser(loggedInUser);
    });

    const logout = (e) => {
        e.preventDefault();
        const headers = {
            "Accept" : "application/json",
            "Authorization" : `Bearer ${localStorage.getItem('loginToken')}`
        };
    
        axios.post('http://website.test/api/logout', null, {headers})
            .then(res => {
                console.log(res);
                if(res.status === 200) {
                    localStorage.clear();
                    return history.push('/');
                }
            }).catch(err => {
            console.log(err);
        });
    };

    return (
        <>
            <Navbar bg="dark" variant="dark">
                <Container>
                    <Navbar.Brand href="#home">Navbar</Navbar.Brand>
                    { loggedInUser ? <Nav className="me-auto"><Button onClick={logout}>Logout</Button></Nav> : null }
                </Container>
            </Navbar>
        </>
    );
}

export default NavBar;

首先,我不喜欢Redux(也许和你一样),我使用React Tracked(https://github.com/dai-shi/react-tracked),它有一些类似Redux的功能,但使用起来非常简单。

其次,你应该通过dispatch调用APIquery,方便你的逻辑代码的读写。

与 Redux 一样,React Tracked 使用中心状态,但仅在需要时重新加载组件,而不是同时重新加载所有组件。

我的回答是:不刷新页面,不使用 Redux,使用 React Tracked!

注意:useEffect() 应该像这样调用空依赖项:useEffect(()=> {}, [])

localStorage.clear();之前你必须添加setLoggedInUser(false);,如果你在这里放置return history.push('/');,你的页面将被重新加载!

如果本地存储发生变化,React 不会收到“通知”。 React 仅对状态(useState、context、redux 等)变化做出反应。最简单的方法是这样的:

--App.jsx

const App = () => {
  const [userState, setUserState] = useState(localStorage.getItem("loginToken"));

  return (
   <>
     <Navigation userState={userState} setUserState={setUserState} />
     {!userState && <Login setUserState={setUserState} />}
   </>
  )
}

--Login.jsx

const Login = ({ setUserState }) => {
  const onLoginButtonClick = () => {
    //.. do api request
    setUserState('myState')
  }
  return (
    <button onClick={onButtonClick} />
  )
}

--Navigation.jsx

const Navigation = ({ userState, setUserState }) => {
 const onLogoutButtonClick => {
  //..do api request
  localStorage.setItem('loginToken', null);
  setUserState(null);

 }
 return (
  <>
   <div>some things</div>
   { userState && <button onClick={onLogoutButtonClick}>logout</button> }
  </>
 )
}