坚持 React 登录用户

问题描述 投票:0回答:1

我可以在我的 React-Django 应用程序中注册、登录和注销用户。我在登录时在本地存储中设置用户数据(用户名、电子邮件等)。但是,当我尝试转到受保护的路由(例如“/about”)时,我被重定向到“/login”,因为 React 在尝试访问受保护的路由时似乎无法足够快地检查用户状态路线。当我访问受保护的路由时,我正在控制台记录用户状态,只是为了证明该状态仍然存在,但检索速度不够快(在渲染之前)。

当我登录然后转到受保护的“/about”路由时,我的 console.logs 是:

AuthContext state:  {user: null}
AuthContext state:  {user: null}
AuthContext state:  {user: {…}}
AuthContext state:  {user: {…}}

所以,在受保护的页面呈现之前,我需要帮助以足够快的速度访问用户状态。想法?

这是我的代码:

src/context/AuthContext.js:

export const AuthContext = createContext()

export const authReducer = (state, action) => {
    switch (action.type){
        case "LOGIN":  
            return { user: action.payload }
        case "LOGOUT": 
            localStorage.removeItem("mysUser")
            return { user: null }
        default: 
        return state
    }   
}

export const AuthContextProvider = ({ children }) =>{
    
    const [state, dispatch] = useReducer(authReducer, {
        user: null
    })

    useEffect(() => {
        const user = JSON.parse(localStorage.getItem("mysUser"))
        if (user){
            dispatch({ type: "LOGIN", payload: user })
        }
    }, [])

    console.log("AuthContext state: ", state)
    return (
        <AuthContext.Provider value={{ ...state, dispatch}}>
            { children }
        </AuthContext.Provider>
    )
}

src/App.js


function App() {

  // auth state
  const { user } = useAuthContext()


  return (
    <div className="App">
      <BrowserRouter>
        <NavbarComponent/>
        <div>

          <Routes>
          
          {/* protected route */}
          <Route
              path="/about"
              element={user ? <About /> : <Navigate to="/login" />}
              exact
            />
            

          {/* non-protected routes */}
          <Route path="/" element={<Home />} />

          <Route path="/signup" element={<Signup />} exact />
          <Route path="/login" element={<Login/>} exact />
        </Routes>
          
        </div>
        <FooterComponent />
      </BrowserRouter>
    </div>
  );
}

export default App;

reactjs local-storage
1个回答
0
投票

在你的

App
函数中你可以这样做

是的,useEffect 确实在渲染后运行,但如果您这样做,链接将在用户可用时更新。

因为您的自定义钩子已经在渲染发生之后而不是之前触发。您可以使用 useEffect 观察变化并与用户一起更新状态值,这将导致重新渲染,但您不会注意到重新渲染,因为您只是在幕后交换组件。

import {useState, useEffect} from 'react'; //added

function App() {
  const [currUser, setCurrUser] = useState(null) //added

  // auth state
  const { user } = useAuthContext()

  useEffect(() => { //added
    if(user) {
      setCurrUser(user);
    }
  }, [user]) 
  


  return (
    <div className="App">
      <BrowserRouter>
        <NavbarComponent/>
        <div>

          <Routes>
          
          {/* protected route */}
          {/* changed user to currUser */}
          <Route
              path="/about"
              element={currUser ? <About /> : <Navigate to="/login" />}
              exact
            />
            

          {/* non-protected routes */}
          <Route path="/" element={<Home />} />

          <Route path="/signup" element={<Signup />} exact />
          <Route path="/login" element={<Login/>} exact />
        </Routes>
          
        </div>
        <FooterComponent />
      </BrowserRouter>
    </div>
  );
}

export default App;
© www.soinside.com 2019 - 2024. All rights reserved.