Require cycle while requiring store in axios
Asked Answered
Y

1

9

In a reactive native application which is using a redux-saga architecture plus axios, I want to intercept 401 requests and dispatch an action which sends me to a login screen.

So in my axios client, I have:

axiosInstance.interceptors.response.use(
(response) => {
    return response
},
(error) => {

    // token expired
    if (error.response.status === 401) {
        console.log(`401 interceptor error: ${JSON.stringify(error)}`)
        store.dispatch({type: "UNAUTHORIZED_RESPONSE_RECEIVED"})
    }
    return Promise.reject(error)
}
)

Now, while this works, the problem is I am having a require cycle:

Require cycle: redux/store.js -> redux/sagas.js -> redux/project/saga.js -> helpers/projectHelper.js -> helpers/client.js -> redux/store.js

This is obvious, but since to create the store I am applying the sagaMiddleware, to define it I import my sagas, in which I import the projectHelper file (which is a series of axios ajax api calls) in which I import the client which, to be able to perform the store.dispatch() needs to import the store, following the option no.1 from this series of options:

https://daveceddia.com/access-redux-store-outside-react/#option-1-export-the-store

Everything works, but this warning worries me a little bit.

Require cycles are allowed, but can result in uninitialized values. Consider refactoring to remove the need for a cycle.

My question is: how could I find other (also creative) ways to achieve what I need, which is:

  1. intercept the 401 (not putting it into every saga action that fails)

  2. (optional) dispatch an action which ends up ->

  3. sending me to the "Login" Screen?

Yasmin answered 19/5, 2019 at 17:12 Comment(2)
I have the same question. Did you ever find a creative answer to this?Outlandish
I found a solution that might help you, I just posted as an answer in case is useful for others.Yasmin
Y
0

For anyone having trouble with this use case, this was the solution I adopted.

In one of my app main components (might be App.tsx), I put an Axios interceptor

    componentDidMount() {


    const self = this;
    axios.interceptors.request.use(
      function(config: AxiosRequestConfig) {

       // useful to show a loader
       self.props.loading(true);

        return config;
      },
      function(error) {
        return Promise.reject(error);
      }
    );

    axios.interceptors.response.use(
      function(response) {
        // loader stops
        self.props.loading(false);

        return response;
      },
      function(error) {
        self.props.loading(false);
        if (
          typeof error.response !== "undefined" &&
          error.response.status === 401
        ) {
          console.log(`401 interceptor error: ${JSON.stringify(error)}`);

          NavigationService.navigate("Login", null);
        }
        if (
          typeof error.message !== "undefined" &&
          error.message == "Network Error"
        ) {
          console.log(`Network Error`);
        }
        return Promise.reject(error);
      }
    );

Not perfect, but I hope it could be useful for people trying to achieve this!

Yasmin answered 10/5, 2020 at 21:7 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.