Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Intercept actions and re-add to the queue when throws errors like "Network Error" #284

Closed
helderberto opened this issue Jul 30, 2020 · 7 comments · Fixed by #286
Closed

Comments

@helderberto
Copy link
Contributor

helderberto commented Jul 30, 2020

Current Behavior

I follow this guide, but after method dispatch to FETCH_OFFLINE_MODE don't re-add to the queue, like the following image:
Screen Shot 2020-07-30 at 18 35 18

After that, I check in the network from redux store and method aren't add again. How I can execute again the old queue item?

The method makeOffline involves the thunk is like the following:

import { isArrayEmpty } from '_utils/validation';

const makeOffline = ({
  thunk = function() {},
  methodName = '',
  dismiss = [],
  args = [],
}) => {
  thunk.interceptInOffline = true;

  thunk.meta = {
    retry: true,
    name: methodName,
    args: !args || isArrayEmpty(args) ? [] : args,
    dismiss: [],
  };

  return thunk;
};

export default makeOffline;

This is a sample of my actions:

export const createSchedule = (scheduling, offlineArgs = {}) =>
  makeOffline({
    thunk: async (dispatch, getState) => {
      const { actualHolding } = getState().holding;

      analytics().logEvent('action_create_schedule', {
        status: 'pending',
      });

      const { changeQueueSemaphore } = offlineActionCreators;
      dispatch(changeQueueSemaphore('RED'));
      try {
        const { data } = await SchedulingService.createSchedule(
          actualHolding,
          scheduling,
        );
        dispatch(changeQueueSemaphore('GREEN'));

        analytics().logEvent('action_create_schedule', {
          status: 'success',
        });

        return dispatch({
          type: Types.CREATE_SCHEDULING_SUCCESS,
          payload: data,
        });
      } catch (error) {
        dispatch(changeQueueSemaphore('GREEN'));
        dispatch(offlineActionCreators.fetchOfflineMode(createSchedule));
        analytics().logEvent('action_create_schedule', {
          status: 'error',
        });

        console.log('createSchedule error:', error);
      }
    },
    methodName: 'createSchedule',
    args: [scheduling, offlineArgs],
  });

Note: I tried to apply the semaphore to avoid run when receiving errors, but doesn't work as expected.

Expected Behavior

  • Re-add action to the queue when throws errors.

How to reproduce

  • Execute actions in airplane mode to add to the queue;
  • Put connection online;
  • When start dispatch, turn on airplane mode again in the middle of dispatching;

Your Environment

software version
react-native-offline v5.7.0
react-native v0.61.4
redux-persist v6.0.0
axios v0.19.0
node v12.18.3
yarn v1.22.4
@helderberto
Copy link
Contributor Author

Hey, @rgommezz just to check, the package is still being maintained?

@rgommezz
Copy link
Owner

Hey @helderburato,

By looking at your code I noticed something odd inside your catch clause. It seems you are using fetchOfflineMode incorrectly. fetchOfflineMode receives as argument either a redux action (plain object) or a thunk (function that receives dispatch and getState as arguments). However, you are trying to add something the library doesn't understand. See my comment below.

catch (error) {
        dispatch(changeQueueSemaphore('GREEN'));
		// You are NOT dispatching a thunk here
        dispatch(offlineActionCreators.fetchOfflineMode(createSchedule));
        analytics().logEvent('action_create_schedule', {
          status: 'error',
        });

        console.log('createSchedule error:', error);
      }

@helderberto
Copy link
Contributor Author

helderberto commented Aug 11, 2020

Hey @helderburato,

By looking at your code I noticed something odd inside your catch clause. It seems you are using fetchOfflineMode incorrectly. fetchOfflineMode receives as argument either a redux action (plain object) or a thunk (function that receives dispatch and getState as arguments). However, you are trying to add something the library doesn't understand. See my comment below.

catch (error) {
        dispatch(changeQueueSemaphore('GREEN'));
		// You are NOT dispatching a thunk here
        dispatch(offlineActionCreators.fetchOfflineMode(createSchedule));
        analytics().logEvent('action_create_schedule', {
          status: 'error',
        });

        console.log('createSchedule error:', error);
      }

Hey @rgommezz, thanks for your reply!

Can you give me an example using a thunk method?
I'm using a thunk in this case and just have a wrapper method called makeOffline I saw the docs, but I don't understand what specifically the package needs to re-dispatch.


I read this part of the documentation, but I didn't understand at the point that you mention about the action/thunk, what should be passed as a parameter to offlineActionCreators.fetchOfflineMode(action)?

@rgommezz
Copy link
Owner

rgommezz commented Aug 11, 2020

In your example, the thunk would be the result of calling createSchedule(scheduling), so that's what you'd have to dispatch. You are instead dispatching the thunk factory function, but not the thunk itself.

dispatch(offlineActionCreators.fetchOfflineMode(createSchedule(scheduling));

I read this part of the documentation, but I didn't understand at the point that you mention about the action/thunk, what should be passed as a parameter to offlineActionCreators.fetchOfflineMode(action)?

Agree, the documentation could be better in that section since an action is meant to be a plain object, but in this case it rather refers to thunks

@helderberto
Copy link
Contributor Author

I fixed the problem with the following way:

export const createSchedule = (scheduling, offlineArgs = {}) => {
  function thunk(dispatch, getState) {
    const { actualHolding } = getState().holding;

    SchedulingService.createSchedule(actualHolding, scheduling)
      .then(({ data }) => {
        dispatch({
          type: Types.CREATE_SCHEDULING_SUCCESS,
          payload: data,
        });
      })
      .catch(error => {
        console.error('createSchedule:', error);
        dispatch(offlineActionCreators.fetchOfflineMode(thunk));
      });
  }

  thunk.interceptInOffline = true;

  thunk.meta = {
    retry: true,
    name: 'createSchedule',
    args: [scheduling, offlineArgs],
  };

  return thunk;
};

Your comment really helped me to fix it, I'll submit a PR to improve the docs, what do you think? @rgommezz

@rgommezz
Copy link
Owner

That sounds great @helderburato, looking forward to it!

@helderberto
Copy link
Contributor Author

That sounds great @helderburato, looking forward to it!

Submitted #286 💯

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants