suchen

Heim  >  Fragen und Antworten  >  Hauptteil

Titel umgeschrieben in: Geschützte Routen in React Route v6 werden nicht aktualisiert, wenn sich der Benutzer anmeldet

<p>Ich versuche, einen Benutzer anzumelden. Ich habe eine Anmeldekomponente, die die Anmeldeinformationen empfängt, und dann verwende ich das Redux-Toolkit, um den Status und die Validierung zu speichern, und alles wird in userSlice erledigt. Ich habe eine geschützte Route, die prüfen soll, ob der Benutzer angemeldet ist. Wenn der Benutzer nicht angemeldet ist, sollte sie nicht zu meiner Rezeptseite navigieren. Wenn ich versuche, über den useSelecter-Hook von einer geschützten Routing-Komponente aus auf den Benutzer zuzugreifen, wird beim ersten Rendern null zurückgegeben, beim zweiten Rendern jedoch der Benutzer, aber die Anmeldung schlägt immer noch fehl. In Redux-Entwicklungstools wird der Status gut aktualisiert. Gibt es eine Möglichkeit, das Benutzerobjekt beim ersten Rendern der geschützten Routing-Komponente abzurufen? (Wie Sie sehen können, verwende ich den useEffect-Hook und habe ein Abhängigkeitsarray.) </p> <p>Vielen Dank für Ihre Hilfe. Danke. </p> <p>Hier ist mein Code: </p> <p>Login.js – Diese Datei ist für den Empfang der Anmeldeinformationen, das Auslösen einer Aktion mithilfe von useDispatch und die Aktualisierung des Status mithilfe von useDispatch verantwortlich. </p> <pre class="brush:php;toolbar:false;">import React, { useState } from 'react'; import { loginUser } from '../../features/users/userSlice'; importiere { useSelector, useDispatch } aus 'react-redux' import { useNavigate } from 'react-router-dom'; Standardfunktion Login() exportieren { const [email, setEmail] = useState(""); const [password, setPassword] = useState(""); const user = useSelector(state => state.user.user) const distribution = useDispatch() const navigation = useNavigate() zurückkehren ( <div> <Eingabe type="text" value={email} onChange={(e) => setEmail(e.target.value)} /> <Eingabe type="Passwort" value={Passwort} onChange={(e) => setPassword(e.target.value)} /> <button type="submit" onClick={() => Versand(loginUser({E-Mail, Passwort})) navigieren('/Rezepte') }}>senden</button> </div> ) }</pre> <p>ProtectedRoute.js – Diese Komponente stellt sicher, dass sich der Benutzer nicht anmelden kann, wenn er nicht authentifiziert ist.</p> <pre class="brush:php;toolbar:false;">import React, { useState, useEffect } from "react"; import { Route, Navigate, Outlet } from "react-router-dom"; import { useSelector } aus 'react-redux'; Exportieren Sie die Standardfunktion ProtectedRoute({children }) { const [ activeUser, setActiveUser ] = useState(false) const user = useSelector((state) => state.user); useEffect(() => { if (!user.isLoading) { user.success ? setActiveUser(true) : setActiveUser(false) console.log('aktiver Benutzer: ' + activeUser) } }, [Benutzer]) zurückkehren ( activeUser ? <Outlet /> <Navigieren zu="/login"/> ) }</pre> <p>app.js – Diese Komponente enthält alle Routen, einschließlich geschützter Routen. </p> <pre class="brush:php;toolbar:false;">import React from "react"; Importieren Sie Rezepte aus „./components/recipes/recipes“; Login aus „./components/users/Login“ importieren; import { BrowserRouter, Routes, Route, Navigate } from "react-router-dom"; importiere ProtectedRoute aus „./utils.js/ProtectedRoute“; const App = () => zurückkehren ( <div> <BrowserRouter> <Routen> <Route path="/login" index element={<Login />} /> <Route path="/" element={<Navigieren ersetzen zu="/login" <Route element={<ProtectedRoute />}> <Route element={<Recipes/>} path="/recipes" </Route> </Routen> </BrowserRouter> </div> ); }; Standard-App exportieren;</pre> <p>userSlice.js – 由于我使用redux toolkit,因此我有不同功能的slices。这里有reducers,其中有用户状态。</p> <pre class="brush:php;toolbar:false;">import { createSlice, createAsyncThunk } from "@reduxjs/toolkit"; Axios aus „Axios“ importieren; const loginUrl = 'http://localhost:5000/api/login'; const signupUrl = 'http://localhost:5000/api/signup'; export const loginUser = createAsyncThunk('user/loginUser', async (data) => { const Antwort = Warten auf axios.post(loginUrl, data); Rückantwort; }) export const signupUser = createAsyncThunk('user/signupUser', async (data) => { const Response = Warten auf axios.post(signupUrl, data); Rückantwort; }) const initialState = { Benutzer: {}, isLoading: wahr } const userSlice = createSlice({ Name: 'Benutzer', Ausgangszustand, Reduzierstücke: { getPassword: (Zustand, Aktion) => { const passwort = action.payload console.log (Passwort) } }, extraReducers: { [loginUser.pending]: (state) => { state.isLoading = false }, [loginUser.fulfilled]: (Zustand, Aktion) => { state.isLoading = false state.user = action.payload.data }, [loginUser.rejected]: (state) => { state.isLoading = false }, [signupUser.pending]: (state) => { state.isLoading = false }, [signupUser.fulfilled]: (Status, Aktion) => { state.isLoading = false state.user = action.payload.data }, [signupUser.rejected]: (state) => { state.isLoading = false }, } }) export const { getPassword } = userSlice.actions Standard exportieren userSlice.reducer;</pre></p>
P粉297434909P粉297434909484 Tage vor478

Antworte allen(1)Ich werde antworten

  • P粉043432210

    P粉0434322102023-08-30 12:24:05

    问题在于登录处理程序同时发出了两个动作。

    onClick={() => {
      dispatch(loginUser({ email, password })); // <-- 登录用户
      navigate('/recipes');                     // <-- 立即导航
    }}
    

    在用户进行身份验证之前,导航到受保护的路由。

    为了解决这个问题,登录处理程序应该等待成功的身份验证,然后重定向到所需的路由。

    const loginHandler = async () => {
      try {
        const response = await dispatch(loginUser({ email, password })).unwrap();
        if (/* 检查响应条件 */) {
          navigate("/recipes", { replace: true });
        }
      } catch (error) {
        // 处理任何错误或被拒绝的 Promise
      }
    };
    
    ...
    
    
    onClick={loginHandler}
    

    更多详细信息请参见处理 Thunk 结果

    您还可以简化ProtectedRoute逻辑,不需要额外的重新渲染,只需获取正确的输出进行渲染。所有路由保护状态都可以从选择的 redux 状态中派生。

    export default function ProtectedRoute() {
      const user = useSelector((state) => state.user);
    
      if (user.isLoading) {
        return null; // 或者加载指示器/旋转器等
       }
    
      return user.success ? <Outlet /> : <Navigate to="/login" replace />;
    }

    Antwort
    0
  • StornierenAntwort