首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >私有路由在呈现组件之前获取身份验证

私有路由在呈现组件之前获取身份验证
EN

Stack Overflow用户
提问于 2021-01-02 12:15:18
回答 2查看 250关注 0票数 0

我在使用带身份验证的用户的PrivateRoute时遇到问题。

因为我使用redux来捕获用户的身份验证,所以在呈现组件之前,我需要等待state从存储返回。如果不是,页面将自动重定向到login route

我的问题是,当前路由在等待身份验证结果时会被重定向到登录页面。如果通过身份验证,将返回页面。

所以我想先等authentication result。如果通过认证,将加载页面组件,否则将重定向到登录页面。

这是我的带身份验证的私有路由。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import React from "react";
import { Route, Redirect} from "react-router-dom";
import { connect } from "react-redux";

const PrivateRoute = ({ component: Component, auth, role, ...rest }) => {    
  return (
    <Route
      {...rest}
      render={props => auth.isAuthenticated ? (
          <Component {...props} />
        ) : (          
          <Redirect  to={{
            pathname: "/",
            state: { from: props.location }
          }} />
        )
      }
    />
  )
}

const stateStoreToProp = state => ({
  auth: state.loginReducer,
});
export default connect(stateStoreToProp)(PrivateRoute);

这是我的自动重定向的登录组件。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
  let history = useHistory();
  let location = useLocation();

  let { from } = location.state || { from: { pathname: "/choose" } };
  const isAuthenticated = prop.loginReducer.isAuthenticated;
  const user = prop.loginReducer.user;
  if (isAuthenticated && typeof user !== "undefined") {
    history.replace(from);
  }

这是App.js

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import { loadUser } from './actions/AuthAction';
function App() {
    useEffect(() => {
      store.dispatch(loadUser()); 
    }, []);
    return (
      <Provider store={store}>
        <Router>
          <Fragment>
            <div className="blockcontain">
              <div className="fss">
                <div className="rightSide">
                  <Switch>
                    <Route path='/' exact component={Login} />
                    <PrivateRoute exact path='/choose' component={Choose} />
                  </Switch>
                </div>
              </div>
            </div>
          </Fragment>
        </Router>
      </Provider>
    );  
}

和LoginReducer

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import {
  LOGIN_SUCCESS, LOGIN_FAIL, USER_LOADED, AUTH_ERROR
} from '../actions/typeName';
import Cookies from 'js-cookie';
const initialState = {
  token: Cookies.get('token'),
  isAuthenticated: null,
  loading: true, 
  user: null
}
const loginReducer = (state = initialState, action) => {
  const {type, payload} = action; 

  switch(type) {
      case USER_LOADED:
        return {
          ...state,
          isAuthenticated: true,
          loading: false,
          user: payload
        };
      case LOGIN_SUCCESS:
        Cookies.set('token', payload.access_token, { expires: payload.expires_at });
        return {
          ...state,
          isAuthenticated: true, 
          loading: false
        }
      case AUTH_ERROR:
      case LOGIN_FAIL:
          return {
            ...state,
            token:null,
            isAuthenticated: false,
            loading: true
          }
      default:
          return state;
  }
}

export default loginReducer;

我去choose page,它将转到登录页面,因为store for authentication还没有准备好。

谢谢。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2021-01-02 12:40:48

您可以将加载属性添加到您的状态,并仅在获取完成后显示路由:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
const PrivateRoute = ({ component: Component, auth, isLoading, role, ...rest }) => {
  if(isLoading) return <div>Loading...</div>;
  
  return (
    <Route
      {...rest}
      render={(props) =>
        auth.isAuthenticated ? (
          <Component {...props} />
        ) : (
          <Redirect
            to={{
              pathname: '/',
              state: { from: props.location },
            }}
          />
        )
      }
    />
  )
}

const stateStoreToProp = (state) => ({
  isLoading: state.loading,
  auth: state.loginReducer,
})

export default connect(stateStoreToProp)(PrivateRoute)

并在你的reducer中添加加载突变,例如:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
case REQUEST_LOGIN:
      return [...state, isLoading: true];
case LOGIN_SUCCESSFUL:
      return [...state, auth: isAuthenticated, isLoading: false];
票数 1
EN

Stack Overflow用户

发布于 2021-01-02 12:41:19

您可以做的是添加一个“正在加载”的密钥到您的身份验证状态,因此当它进行身份验证时,状态将为"true“,否则为"false”。如果为真,则显示一个加载器。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import React from "react";
import { Route, Redirect} from "react-router-dom";
import { connect } from "react-redux";

const PrivateRoute = ({ component: Component, auth, role, ...rest }) => {
    
  return (
    <>
      {
        auth.loading && (
          <Loader/>
        )
      }

      {
        !auth.loading && (
          (
            <Route
            {...rest}
            render={props => auth.isAuthenticated ? (
                <Component {...props} />
              ) : (          
                <Redirect  to={{
                  pathname: "/",
                  state: { from: props.location }
                }} />
              )
            }
          />          
          )          
        )
      }
    </>
  )
}


const stateStoreToProp = state => ({
  auth: state.loginReducer,
});
export default connect(stateStoreToProp)(PrivateRoute);
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/65538978

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文