当将调度放入Axios拦截器时,调度不工作

z3yyvxxp  于 2023-02-12  发布在  iOS
关注(0)|答案(1)|浏览(119)

我在axios拦截器中使用了dispatch事件,这样每当我从API中得到400错误时,我就会将事件发送到UI,以通知消息和重定向。请参阅

export const loggerInterceptor = (AXIOS ) => {
      const { request, response } = AXIOS.interceptors;
      const token = getCookie(COOKIE_JWT_TOKEN);
      
      request.use((config) => {
        config.performance = calculateTimes();
        config.timestamp = Date.now();
        return config;
      });
    
      response.use(
        (response) => {
          if (
            response
          ) {
            flightInfo = {
              ...flightInfo,
              ...response.data,
            };
          }
          return Promise.resolve(response);
        },
        (error) => {
         if(error.response.status===400)
          {
            addErrorToast();
           window.location.href= window.location.origin +'/app';
            
          } 
          return Promise.reject(error);
        }
      );
    };

下面的addErrorToast是正确触发时,我得到400错误,但调度没有发生.任何解决方案或建议,以解决这个问题

const addErrorToast = ()=>{
  const dispatch = useDispatch();
  dispatch(
          addToast({
            type: "success",
            msg: (
              <FormattedMessage
                id="notifications.connected"
                defaultMessage="You are connected!"
              />
            ),
            hasCloseIcon: false,
          })
      );
}
2eafrhcq

2eafrhcq1#

您是否在Redux提供程序 Package 器之外导入此Axios配置?这是一个很容易犯的错误,因为此配置通常导入到基本index.tsx/main.tsx文件中,Redux Package 器设置在同一文件或App.tsx中,在这两种情况下,您的Axios配置将无法导入dispatch
确保你在Redux提供者 Package 器中导入了这个axios配置。你还想***把你的拦截器变成一个钩子***这样它就可以使用其他钩子了。

    • 这行不通**
    • 索引. js**
import ReactDOM from 'react-dom';
import { BrowserRouter } from 'react-router-dom';
import { Provider } from 'react-redux'
import store from './store'
import App from './App';
import initAxios from './config/axios';

initAxios(); <--- Not proper hook format (i.e. useXYZ)

ReactDOM.render(
  <BrowserRouter>
    <Provider store={store}>   <--- Store does not wrap Axios
      <App />
    </Provider>
  </BrowserRouter>,
  document.getElementById('root'),
);
    • 工作示例:React18 + Redux + Axios拦截器派遣**

我创建了一个沙箱,其中包含一个Axios拦截器需要分派到Redux的工作示例。
https://codesandbox.io/p/sandbox/react18-axios-interceptor-dispatch-to-redux-jiin13

    • 索引. js**
import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import App from "./App";
import store from "./store";
import { Provider } from "react-redux";

/*
// axios interceptor must be contained within the redux store, App.js
import useAxiosInterceptor from "./useAxiosInterceptor";

useAxiosInterceptor();
*/

const rootElement = document.getElementById("root");
const root = createRoot(rootElement);

root.render(
  <StrictMode>
    {" "}
    {/* <--- 2 renders expected */}
    <Provider store={store}>
      <App />
    </Provider>
  </StrictMode>
);
    • 应用程序. js**
import { useEffect } from "react";
import { useSelector, useDispatch } from "react-redux";
import { decrement, increment } from "./counterSlice";
import axios from "axios";
import useAxiosInterceptor from "./useAxiosInterceptor";

export default function App() {
  useAxiosInterceptor();

  const count = useSelector((state) => state.counter.value);
  const dispatch = useDispatch();

  useEffect(() => {
    (async () => {
      try {
        const results = await axios.get("https://www.google.com");
        console.log({ results });
      } catch (e) {
        // console.log(e);
      }
    })();
  }, []);

  return (
    <div>
      <div>
        <button
          aria-label="Increment value"
          onClick={() => dispatch(increment())}
        >
          Increment
        </button>
        <span>{count}</span>
        <button
          aria-label="Decrement value"
          onClick={() => dispatch(decrement())}
        >
          Decrement
        </button>
      </div>
    </div>
  );
}
    • 使用Axios拦截器. js**
import axios from "axios";
import { useDispatch } from "react-redux";
import { increment } from "./counterSlice";

const useAxiosInterceptor = () => {
  const dispatch = useDispatch();

  axios.interceptors.request.use((req) => {
    return req;
  });
  axios.interceptors.response.use((res) => {
    return res;
  });
  axios.interceptors.response.use(
    (res) => res,
    (err) => {
      console.log("##### AXIOS ERROR #####");
      dispatch(increment());
    }
  );

  return null;
};

export default useAxiosInterceptor;
    • 存储. js**
import { configureStore } from "@reduxjs/toolkit";
import counterReducer from "./counterSlice";

export default configureStore({
  reducer: {
    counter: counterReducer,
  },
});
    • 计数器切片. js**
import { createSlice } from "@reduxjs/toolkit";

export const counterSlice = createSlice({
  name: "counter",
  initialState: {
    value: 0,
  },
  reducers: {
    increment: (state) => {
      // Redux Toolkit allows us to write "mutating" logic in reducers. It
      // doesn't actually mutate the state because it uses the Immer library,
      // which detects changes to a "draft state" and produces a brand new
      // immutable state based off those changes
      state.value += 1;
    },
    decrement: (state) => {
      state.value -= 1;
    },
    incrementByAmount: (state, action) => {
      state.value += action.payload;
    },
  },
});

// Action creators are generated for each case reducer function
export const { increment, decrement, incrementByAmount } = counterSlice.actions;

export default counterSlice.reducer;
    • 包. json**
{
  "name": "react",
  "version": "1.0.0",
  "description": "React example starter project",
  "keywords": [
    "react",
    "starter"
  ],
  "main": "src/index.js",
  "dependencies": {
    "@reduxjs/toolkit": "^1.9.2",
    "axios": "^1.3.2",
    "react": "18.2.0",
    "react-dom": "18.2.0",
    "react-redux": "^8.0.5",
    "react-scripts": "^5.0.1"
  },
  "devDependencies": {
    "@babel/runtime": "7.13.8",
    "typescript": "4.1.3"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test --env=jsdom",
    "eject": "react-scripts eject"
  },
  "browserslist": [
    ">0.2%",
    "not dead",
    "not ie <= 11",
    "not op_mini all"
  ]
}

希望能帮上忙!

相关问题