简体   繁体   English

使用 React 处理身份验证的最佳方法是什么?

[英]What's the best way to handle authentication with React?

I have a ProtectedRoute component:我有一个ProtectedRoute组件:

import React, { useState, useEffect, useContext } from 'react';
import CreateRecipe from "./components/CreateRecipe";
import Login from "./components/Login";
import Register from "./components/Register";
import UserContext from './contexts/UserContext';
import Homepage from './components/Homepage';
import LandingPage from './components/LandingPage';
import EditRecipe from './components/EditRecipe';
import SearchPage from './components/SearchPage';
import ViewRecipe from './components/ViewRecipe';
import { BrowserRouter, Route, Redirect } from 'react-router-dom';
import axios from 'axios';


/**
 * Used for Routes that cannot be accessed without authentication
 */
function ProtectedRoute({ component: Component, ...rest }) {
  const [authCheck, setAuthCheck] = useState({ isAuth: false, loading: true });
  const { auth } = useContext(UserContext.context);

  //async call to check authentication status
  useEffect(() => {
    axios.get('/authUser').then(res => {
      setAuthCheck({ isAuth: res.data.isAuth, loading: false });
    });
  }, []);

  return (

    <Route {...rest} render={(props) =>
      (!authCheck.loading) ? (authCheck.isAuth || auth) ? (<Component {...props} />) : (<Redirect to={{
        pathname: "/login",
        state: { from: props.location },
      }} />)
        : (<div>loading</div>)
    } />
  );

}

function App() {

  return (
    <div>
      <BrowserRouter>
        <UserContext>
          <ProtectedRoute component={Homepage} path="/:username/home" />
          <ProtectedRoute path='/:username/edit/:id' component={EditRecipe} />
          <ProtectedRoute path='/:username/create' component={CreateRecipe} />
          <ProtectedRoute path='/:username/search/:q' component={SearchPage} />
          <ProtectedRoute path='/:username/view/:id' component={ViewRecipe} />
          <Route path='/login' component={Login} />
        </UserContext>
        <Route path='/register' component={Register} />
        <Route exact path="/" component={LandingPage} />
      </BrowserRouter>
    </div>
  );
}

export default App;

I found that the useEffect hook fires before the component is even rendered.我发现 useEffect 钩子在组件渲染之前就触发了。 This causes authCheck.isAuth to be permanently be false, thus preventing the user from logging in. To get around that, I made my login component update the context's auth state.这会导致authCheck.isAuth永久为假,从而阻止用户登录。为了解决这个问题,我让我的登录组件更新了上下文的身份验证 state。

How would I get around the useEffect issue?我将如何解决 useEffect 问题? Also, is there a better way to set up authentication on the client side?另外,有没有更好的方法在客户端设置身份验证?

Refactor the .then() to an async await ..then()重构为async await It should update the isAuth state correctly, and then you can remove the auth context.它应该正确更新isAuth state,然后您可以删除auth上下文。

const getAuthUser = async() => {
  try {
    const res = await axios.get('/authUser');
    setAuthCheck({ isAuth: res.data.isAuth, loading: false });
  } catch (e) {
    // handle the error
  } 
};

//async call to check authentication status
useEffect(() => {
  getAuthUser();
}, []);


return (

  <Route {...rest} render={(props) =>
    !authCheck.loading ? authCheck.isAuth ? (<Component {...props} />) : 
    (<Redirect to={{
      pathname: "/login",
      state: { from: props.location },
    }} />)
    : (<div>loading</div>)
   />
);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM