【问题标题】:How redirect user if error.status == 401?如果error.status == 401,如何重定向用户?
【发布时间】:2021-11-24 11:53:01
【问题描述】:

如果请求代码等于 401,我的目标是重定向用户。我编写了以下代码,但它显示错误 401。它显示我 401(来自 console.log,但低于错误)。如果错误等于 401,如何实现重定向?

import axiosConfig from "../../config/axios";
import actions from "./actions";
import { Redirect } from "react-router";
const fetchUser = async () => {
    const response = await axiosConfig.get('api/get-user')
        .catch(function (error) {
            console.log(error.response.status) // 401
            console.log(error.response.data.error) //Please Authenticate or whatever returned from server
            if (error.response.status == 401) {
                return(
                    <Redirect
                        to={{
                            pathname: '/login',
                            state: { from: location },
                        }}
                    />
                );
            }
        });
    return response.data
}
export const getUser = () =>
    async (dispatch) => {
        const user = await fetchUser()
       dispatch(actions.setUser(user));
    }

@更新 路由设置

const Container = () => {
    return (
        <div className="container">
                            <Router>
                                <Switch>
                                    <Route path="/login">
                                        <Login />
                                    </Route>
                                    <Route path="/register">
                                        <Login />
                                    </Route>
                                        <Route path="/all-users">
                                            <Alltasks />
                                        </Route>
                                        <Route path="/all-articles">
                                            <AllUsers />
                                        </Route>
                                </Switch>
                            </Router>
                            <ToastContainer />
        </div>
    );
}

【问题讨论】:

  • 您需要访问history 对象并调用命令式重定向,即history.replace。你能分享你的主路由器设置吗?您还可以分享fetchUser 的调用位置和方式吗?
  • fetchUser 在上面的代码中被调用。如果我考虑过 getUser 函数,请查看它是 Redux 的代码。所以Containercontroller(它在哪里路由)我在mapDispatchToProps和useEffect()中使用它。我更新了我的帖子
  • 啊,是的,我现在明白了,谢谢。你能分享一下你是如何设置你的Router的吗?我怀疑你需要将history对象传递给getUser动作创建者,或者创建一个全局的、可导入的history对象。
  • 看mu代码

标签: reactjs redirect axios http-status-code-401


【解决方案1】:

您不能从这样的操作、实用程序或回调中返回 Redirect 组件,并期望它被渲染并重定向到新路由。您的选择是访问 history 对象并调用命令式重定向。

选项 1

使用connected-react-router 将您的路由器连接到redux。基本要点是创建一个自定义的“createRootReducer”函数,创建一个history 对象,使用“ConnectedRouter”组件。这允许您调度 redux 操作以影响应用中的导航操作。

按照步骤设置路由并将其连接到您的 redux 存储。

在您的异步操作中使用:

import { replace } from 'connected-react-router';

...

const fetchUser = async () => {
  try {
    const response = await axiosConfig.get('api/get-user');
    return response.data;
  } catch (error) {
    if (error.response.status == 401) {
      throw new Error(error);
    }
  }
}

export const getUser = () => async (dispatch) => {
  try {
    const user = await fetchUser();
    dispatch(actions.setUser(user));
  } catch {
    dispatch(replace('/login'));
  }
}

选项 2

创建一个历史对象并在getUser操作中导入和使用。

创建内存、哈希或浏览器历史对象:

import { createBrowserHistory } from 'history';

export const history = new createBrowserHistory();

react-router 导入纯Router 并将历史对象作为道具传递:

import { Router } from 'react-router';
import { history } from '../path/to/custom/history';

...

<Router history={history}>
  ...
</Router>

getUser 操作中导入并使用history

import { history } from '../path/to/custom/history';

...

const fetchUser = async () => {
  try {
    const response = await axiosConfig.get('api/get-user');
    return response.data;
  } catch (error) {
    if (error.response.status == 401) {
      throw new Error(error);
    }
  }
}

export const getUser = () => async (dispatch) => {
  try {
    const user = await fetchUser();
    dispatch(actions.setUser(user));
  } catch {
    history.replace('/login');
  }
}

选项 3

history 对象传递给getUser 操作。

const fetchUser = async () => {
  try {
    const response = await axiosConfig.get('api/get-user');
    return response.data;
  } catch (error) {
    if (error.response.status == 401) {
      throw new Error(error);
    }
  }
}

export const getUser = (history) => async (dispatch) => {
  try {
    const user = await fetchUser();
    dispatch(actions.setUser(user));
  } catch {
    history.replace('/login');
  }
}

用法:

import { useHistory } from 'react-router-dom';

...

const history = useHistory();

...

getUser(history);

...

const mapDispatchToProps = {
  getUser,
};

【讨论】:

  • 选项 2 替换 url 但不刷新组件。我必须按 F5 才能显示登录组件
  • @KaKi786 您是否确保您的Router 通过传递您创建的历史对象使用相同的历史对象?
  • 是的。我确定。我只更改了地址以从 /login 重定向到 main#/login (它的正确地址)
  • @KaKi786 这不会发生在其他两个提议的解决方案中吗?发生这种情况时,我通常会发现开发人员正在使用多个路由器,其中内部路由器处理路由更改并更新地址栏中的 URL,但外部路由器处理渲染路由,因此它永远不会通知路由更改(直到可以读取当前路径的页面重新加载)。
  • 选项 1 不起作用(不替换地址)但我将 dispatch(replace('/login')); 替换为 window.history.replaceState(null, null, "/main#/login") 并且它像选项 2 一样工作 - 替换地址,不刷新组件。当我使用选项 2 时,控制台返回错误 Uncaught (in promise) Error: Actions must be plain objects. Use custom middleware for async actions.
猜你喜欢
  • 1970-01-01
  • 2013-01-06
  • 2019-10-14
  • 2011-05-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-01-06
相关资源
最近更新 更多