javascript 为什么我的React组件没有使用useEffect钩子更新?

g6baxovj  于 2023-06-04  发布在  Java
关注(0)|答案(2)|浏览(147)

我尝试使用react的useEffect钩子来呈现一个组件(SideNavbar),但该组件(SideNavbar)在我手动重新加载页面之前没有变化。当我重新加载页面时,系统工作,但我如何才能做到这一点,而不必手动重新加载页面。
我需要删除一个Sidenavbar时,用户没有登录,并显示导航栏时,用户登录。如何在用户成功登录后立即重新呈现组件?如何在用户注销后立即隐藏组件(SideNavbar)。

import Navbar from "./Components/Navbar";
import React, { useEffect, useState } from "react";
import { Route,Routes } from "react-router";
import Home from "./Routes/Home";
import Contact from "./Routes/Contact";
import Enroll from "./Routes/Enroll";
import Login from "./Routes/Login";
import SideNavbar from "./Components/InnerComponents/SideNavbar";
import Profile from './Routes/Admin/Profile';
import Notice from './Routes/Admin/Notice';
import Result from './Routes/Admin/Result';
import StudentList from "./Routes/Admin/StudentList";
import TeacherList from "./Routes/Admin/TeacherList";
import Classroom from "./Routes/Admin/Classroom";
import NoticeState from "./context/notices/NoticeState";
import NewAccount from "./Routes/Admin/NewAccount.js"
import UserState from "./context/user/UserState";

function App() {
  
  const [isLoggedIn, setIsLoggedIn] = useState(false);

  useEffect(()=>{
    if(localStorage.getItem('token')){
      setIsLoggedIn(true);
    }
  },[localStorage.getItem('token')])
    
  

  return (
    <div className="App">
    <UserState>
      <NoticeState>
        <Navbar/>
        {isLoggedIn && <SideNavbar/>}
        <div className="containerApp">
          <Routes>
            <Route element={<NewAccount/>} exact path='/newaccount' />
            <Route element={<Profile/>} exact path='/profile' />
            <Route element={<Notice/>} exact path="/notice"/>
            <Route element={<Result/>} exact path="/result"/>
            <Route element={<TeacherList/>} exact path="/teacherList" />
            <Route element={<Classroom/>} exact path="/classroom" />
            <Route element={<StudentList/>} path="/classroom/:classID"/>
            

            <Route element={<Home/>} exact path='/' />
            <Route element={<Contact/>} exact path='/contact' />
            <Route element={<Enroll/>}  exact path='/enroll' />
            <Route element={<Login/>}  exact path='/login' />
          </Routes>
        </div>
      </NoticeState>
      </UserState>
    </div>
  );
}

export default App;
mqkwyuun

mqkwyuun1#

问题出在这个useEffect

useEffect(()=>{
    if(localStorage.getItem('token')){
      setIsLoggedIn(true);
    }
  },[localStorage.getItem('token')])

因为在deps数组中,有localStorage.getItem('token'),它被调用once<App/>没有理由重新渲染(这是由setState引起的)。最快的解决方案是创建一个定期检查,检查localStorage中是否有令牌。

useEffect(() => {
   const intervalIntance = setInterval(() => {
      if(localStorage.getItem('token')) setIsLoggedIn(true)
      else setIsLoggedIn(false)
   }, 500); // check every 500 ms

   // on unmount remove the interval to prevent memory leaks
   return () => { clearInterval(intervalInstance) }
},[])

它会工作,但这不是一个理想的解决方案。以下是一些原因:
1.令牌检查-事实上,您拥有令牌并不意味着您已登录。应该检查令牌是否有效、是否过时、是否来自正确的发行者等等。有一些指导如何更正确地做到这一点:oAuth guideanother quite comprehensive guide .你可以在互联网上找到一吨。
1.安全性-将令牌存储在localStorage中很方便,但也有很多很多缺点。它很容易泄漏,所以这不是一个推荐的方法。您可以在this SO post中阅读更多内容。
1.定期检查--这些都远非理想。由于ReactReact系统和自动更新,例如setStateReact.Context值更改,我们应该寻找一个解决方案,在登录并获得令牌后,将导致自动重新呈现<App/>,例如通过更新React.Context值,设置状态。提示是,应该通过设置一个将更新<App/>组件的值,在成功登录时触发此重新呈现。React将负责与重新渲染和显示Sidebar相关的其余工作。

dy2hfwbg

dy2hfwbg2#

当用户成功登录/注销时,需要重新渲染组件。使用useEffect依赖性,如下面代码所述。
查看更新的代码。

import React, { useEffect, useState } from "react";
import { Route, Routes } from "react-router";
import Home from "./Routes/Home";
import Contact from "./Routes/Contact";
import Enroll from "./Routes/Enroll";
import Login from "./Routes/Login";
import SideNavbar from "./Components/InnerComponents/SideNavbar";
import Profile from './Routes/Admin/Profile';
import Notice from './Routes/Admin/Notice';
import Result from './Routes/Admin/Result';
import StudentList from "./Routes/Admin/StudentList";
import TeacherList from "./Routes/Admin/TeacherList";
import Classroom from "./Routes/Admin/Classroom";
import NoticeState from "./context/notices/NoticeState";
import NewAccount from "./Routes/Admin/NewAccount.js";
import UserState from "./context/user/UserState";

function App() {
  const [isLoggedIn, setIsLoggedIn] = useState(false);

  useEffect(() => {
    const token = localStorage.getItem('token');
    setIsLoggedIn(!!token);
  }, []);

  const handleLogin = () => {
    setIsLoggedIn(true);
  };

  const handleLogout = () => {
    localStorage.removeItem('token');
    setIsLoggedIn(false);
  };

  return (
    <div className="App">
      <UserState>
        <NoticeState>
          <Routes>
            <Route element={<NewAccount />} exact path="/newaccount" />
            <Route element={<Profile />} exact path="/profile" />
            <Route element={<Notice />} exact path="/notice" />
            <Route element={<Result />} exact path="/result" />
            <Route element={<TeacherList />} exact path="/teacherList" />
            <Route element={<Classroom />} exact path="/classroom" />
            <Route element={<StudentList />} path="/classroom/:classID" />

            <Route element={<Home />} exact path="/" />
            <Route element={<Contact />} exact path="/contact" />
            <Route element={<Enroll />} exact path="/enroll" />
            <Route
              element={<Login onLogin={handleLogin} />}
              exact path="/login"
            />
          </Routes>
          <Navbar />
          {isLoggedIn && <SideNavbar onLogout={handleLogout} />}
        </NoticeState>
      </UserState>
    </div>
  );
}

export default App;

相关问题