如何通过手动更改URL来避免从已登录页面重定向到主页(登录页面)- React

huangapple go评论150阅读模式
英文:

How to avoid redirect from logged in page to home(login page) by changing the url manually-react

问题

以下是您要翻译的代码部分:

Login.js

const [loginUser, { data, isLoading, isError }] = useLoginUserMutation();
useEffect(() => {
  if (data?.response === "true" && data?.state === "success"){
    setErrorMsg("");
    setEmail("");
    setPassword("");
    setIsAuthenticated(true);
    navigate("/home", { state: { user: data?.user } });
  }
  else if (data?.response === "false" && data.state === "error"){
    setErrorMsg(true);
  }
  else{
    setErrorMsg(false)
  }
}, [data,isError,isLoading]);

const handleLogin = async (e) => {
  e.preventDefault();
  console.log("****")
  await loginUser({email,password})
}

App.js

function App() {
  const [isAuthenticated, setIsAuthenticated] = useState(false);
  const handleLogin = () => {
    setIsAuthenticated(true);
  }

  return (
    <div className="App">
      <Router>
        <Routes>
          <Route exact path="/">
            <Login onLogin={handleLogin} />
          </Route>
          <ProtectedRoute path="/home" component={Home} isAuthenticated={isAuthenticated}/>
        </Routes>
      </Router>
    </div>
  );
}
export default App;

protectedRoute.js

import React from "react";
import { Navigate, Outlet } from "react-router-dom";

const ProtectedRoute = ({ isAuthenticated }) => {
  return isAuthenticated? <Outlet /> : <Navigate to="/" />;
}

export default ProtectedRoute;

UserApi

import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react';

export const authApi = createApi({
  reducerPath: 'authApi',
  baseQuery: fetchBaseQuery({ baseUrl: "http://localhost:8100" }),
  endpoints: (builder) => ({
    loginUser: builder.mutation({
      query: (body) => {
        return {
          url: "users/authenticate",
          method: "post",
          body,
        };
      },
      transformResponse: (response) => {
        const { response: resp, state, user } = response;
        return { response: resp, state: state, user: user };
      },
    }),
  }),
});

export const { useLoginUserMutation } = authApi;

关于在本地存储中持久保存身份验证状态的问题,您尝试使用localStorage是一个合理的方法。但是,由于您正在使用Redux Toolkit,您也可以将身份验证状态存储在Redux store 中,以便更好地与您的应用程序状态管理一起使用。这将取决于您的应用程序的需求和偏好。

英文:

Say the user is already logged in and redirected to home page again if he modifies the url to navigate to login page it should not do go back to login.

Login.js

const [loginUser, { data, isLoading, isError }] = useLoginUserMutation();
useEffect(() =&gt; {
if (data?.response === &quot;true&quot; &amp;&amp; data?.state === &quot;success&quot;){
setErrorMsg(&quot;&quot;);
setEmail(&quot;&quot;);
setPassword(&quot;&quot;);
setIsAuthenticated(true);
navigate(&quot;/home&quot;, { state: { user: data?.user } });
}
else if (data?.response === &quot;false&quot; &amp;&amp; data.state === &quot;error&quot;){
  setErrorMsg(true);
}
  else{
    setErrorMsg(false)
  }
}, [data,isError,isLoading]);

const handleLogin = async (e) =&gt; {
e.preventDefault();
console.log(&quot;****&quot;)
await loginUser({email,password})

}

App.js

function App() {
const [isAuthenticated, setIsAuthenticated] = useState(false);
const handleLogin = () =&gt; {
setIsAuthenticated(true);
}

return (
&lt;div className=&quot;App&quot;&gt;
&lt;Router&gt;
&lt;Routes&gt;
  &lt;Route exact path=&quot;/&quot;&gt;
    &lt;Login onLogin={handleLogin} /&gt;
  &lt;/Route&gt;
  &lt;ProtectedRoute path=&quot;/home&quot; component={Home} isAuthenticated= 
 {isAuthenticated}/&gt;
&lt;/Routes&gt;
&lt;/Router&gt;
&lt;/div&gt;
);
}
export default App;

protectedRoute.js

import React from &quot;react&quot;;
import { Navigate,Outlet } from &quot;react-router-dom&quot;;

const ProtectedRoute = ( {isAuthenticated}) =&gt; {
return isAuthenticated? &lt;Outlet /&gt; : &lt;Navigate to=&quot;/&quot; /&gt;;
}

export default ProtectedRoute;

UserApi

import{createApi,fetchBaseQuery} from&#39;@reduxjs/toolkit/query/react&#39;

export const authApi = createApi({
reducerPath: &#39;authApi&#39;,
baseQuery: fetchBaseQuery({ baseUrl: &quot;http://localhost:8100&quot; }),
endpoints: (builder) =&gt; ({
  loginUser: builder.mutation({
    query: (body) =&gt; {
      return {
        url: &quot;users/authenticate&quot;,
        method: &quot;post&quot;,
        body,
      };
    },
    transformResponse: (response) =&gt; {
      const { response: resp, state, user } = response;
      return { response: resp, state: state, user: user };
    },
  }),
}),
});

export const { useLoginUserMutation } = authApi;
enter code here

I tried persisting the state Auth with local storage, since data wont be available it shows undefined/null.

const isAuthenticated = localStorage.getItem(&#39;data&#39;);

if (isAuthenticated) {
setAuthenticationStatus(true);

since I am using Redux Toolkit I am not sure if I have to use localStorage to persist the data.

Any solution would be appreciated

first render localhost:3000(loginPage)
After successfull LoggedIn localhost:3000/home
Manually i change the URL: localhost:3000/ it comes back to login page

答案1

得分: 1

以下是您要的翻译内容:

主要问题是isAuthenticated状态未持久化到长期存储,并且在应用挂载时也未从长期存储中初始化。

更简单的短期解决方案是使用在App中声明的isAuthenticated状态,并将isAuthenticated状态和更新函数作为属性传递给需要它的路由组件。

为了解决“已认证”用户后续访问"/login"路由的问题,答案是创建另一个路由保护组件,它应用了ProtectedRoutes组件的反向,例如,已认证的用户将被从路由中移除。

路由保护器:

import React from "react";
import { Navigate, Outlet } from "react-router-dom";

// 未认证用户重定向到登录路由
const ProtectedRoute = ({ isAuthenticated }) => {
  return isAuthenticated ? <Outlet /> : <Navigate to="/login" replace />;
};

// 已认证用户重定向到安全路由
const AnonymousRoute = ({ isAuthenticated }) => {
  return isAuthenticated ? <Navigate to="/" replace /> : <Outlet />;
};
function App() {
  // 从本地存储初始化状态
  const [isAuthenticated, setIsAuthenticated] = useState(() => {
    return JSON.parse(localStorage.getItem("auth")) ?? false;
  });

  // 副作用,将状态更改持久化到本地存储
  useEffect(() => {
    localStorage.setItem("auth", JSON.stringify(isAuthenticated));
  }, [isAuthenticated]);

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

  return (
    <div className="App">
      <BrowserRouter>
        <Routes>
          <Route path="/" element={<Navigate to="/home" replace />} />

          <Route element={<AnonymousRoute isAuthenticated={isAuthenticated} />}>
            <Route path="/login" element={<Login onLogin={handleLogin} />} />
            {/* ... 其他“匿名”路由 ... */}
          </Route>

          <Route element={<ProtectedRoute isAuthenticated={isAuthenticated} />}>
            <Route path="/home" element={<Home />} />
            {/* ... 其他“已认证”路由 ... */}
          </Route>
        </Routes>
      </BrowserRouter>
    </div>
  );
}
export default App;
const Login = ({ onLogin }) => {
  const navigate = useNavigate();
  const [loginUser, { data, isLoading, isError }] = useLoginUserMutation();
  ...

  const handleLogin = async (e) => {
    e.preventDefault();

    setErrorMsg("");
    try {
      // 调用突变触发器并等待和解包已解决的响应
      await loginUser({ email, password }).unwrap();

      // 更新认证状态
      onLogin();

      // 重定向回主页
      navigate("/home", { replace: true });
    } catch(error) {
      setErrorMsg(true);
    }
  };

  ...
};
英文:

The main issue is that the isAuthenticated state isn't persisted to any longterm storage and ins't initialized from longterm storage when the app mounts.

The easier short-term solution is to use the isAuthenticated state that's declared in App and pass isAuthenticated state and updater function down as props to the routed components that need it.

To combat the issue of "authenticated" users later accessing the &quot;/login&quot; route the answer is to create another route protection component that applies the inverse of the ProtectedRoutes component, e.g. authenticated users are bounced off the route.

Route protectors:

import React from &quot;react&quot;;
import { Navigate, Outlet } from &quot;react-router-dom&quot;;

// Unauthenticated users redirected to log in route
const ProtectedRoute = ({ isAuthenticated }) =&gt; {
  return isAuthenticated ? &lt;Outlet /&gt; : &lt;Navigate to=&quot;/login&quot; replace /&gt;;
};

// Authenticated users redirected to safe route
const AnonymousRoute = ({ isAuthenticated }) =&gt; {
  return isAuthenticated ? &lt;Navigate to=&quot;/&quot; replace /&gt; : &lt;Outlet /&gt;;
};
function App() {
  // Initialize state from localStorage
  const [isAuthenticated, setIsAuthenticated] = useState(() =&gt; {
    return JSON.parse(localStorage.getItem(&quot;auth&quot;)) ?? false;
  });

  // Side-effect to persist state changes to localStorage
  useEffect(() =&gt; {
    localStorage.setItem(&quot;auth&quot;, JSON.stringify(isAuthenticated));
  }, [isAuthenticated]);

  const handleLogin = () =&gt; {
    setIsAuthenticated(true);
  };

  return (
    &lt;div className=&quot;App&quot;&gt;
      &lt;BrowserRouter&gt;
        &lt;Routes&gt;
          &lt;Route path=&quot;/&quot; element={&lt;Navigate to=&quot;/home&quot; replace /&gt;} /&gt;

          &lt;Route element={&lt;AnonymousRoute isAuthenticated={isAuthenticated} /&gt;}&gt;
            &lt;Route path=&quot;/login&quot; element={&lt;Login onLogin={handleLogin} /&gt;} /&gt;
            {/* ... other &quot;anonymous&quot; routes ... */}
          &lt;/Route&gt;

          &lt;Route element={&lt;ProtectedRoute isAuthenticated={isAuthenticated} /&gt;}&gt;
            &lt;Route path=&quot;/home&quot; element={&lt;Home /&gt;} /&gt;
            {/* ... other &quot;authenticated&quot; routes ... */}
          &lt;/Route&gt;
        &lt;/Routes&gt;
      &lt;/BrowserRouter&gt;
    &lt;/div&gt;
  );
}
export default App;
const Login = ({ onLogin }) =&gt; {
  const navigate = useNavigate();
  const [loginUser, { data, isLoading, isError }] = useLoginUserMutation();
  ...

  const handleLogin = async (e) =&gt; {
    e.preventDefault();

    setErrorMsg(&quot;&quot;);
    try {
      // Call mutation trigger and await and unwrap resolved response
      await loginUser({ email, password }).unwrap();

      // Update the auth state
      onLogin();

      // Redirect back to home
      navigate(&quot;/home&quot;, { replace: true });
    } catch(error) {
      setErrorMsg(true);
    }
  };

  ...
};

huangapple
  • 本文由 发表于 2023年3月31日 04:08:47
  • 转载请务必保留本文链接:https://go.coder-hub.com/75892572.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定