rgommezz/react-native-offline

Option to pass in a custom comparison function to detect similar thunks in queue #206

LiquidSean posted onGitHub

I am curious on thoughts of having a custom comparison function for thunks being added to queue. To elaborate further I would like to have more control over actions being added to the queue. What could help is being able to define a comparison function for actions that will be added to the queue. So when these actions are added a comparison function would be run to determine if a match exists. If a match exists replace current queued action with new one. This comparison is on the thunks actual parameters so IDs or other parameters. This would ensure uniqueness for items added. Thoughts on this would be appreciated.


Hey @LiquidSean, that sounds like a good idea! We could have the default isEqual comparison function to be run, unless a custom one is provided otherwise. We could have a new config prop for the middleware factory, something like queueComparisonFn.

Happy to accept a PR for that :)

posted by rgommezz over 5 years ago

Here is what I am thinking for passing in a comparison Fn. Would this make sense? So you would assign the comparison Fn at the time you would assign interceptOffline property.

export const fetchUser = (url) => {
  function thunk(dispatch) {
    fetch(url)
      .then((response) => response.json())
      .then((responseJson) => {
        dispatch({type: FETCH_USER_SUCCESS, payload: responseJson});
      })
      .catch((error) => {
        console.error(error);
      });
  };

  thunk.interceptInOffline = true;
  thunk.queueComparisonFn = someFn;
  return thunk; // Return it afterwards
};
posted by LiquidSean over 5 years ago

I'd prefer having a generic comparison function that applies to all the actions in the queue. You'd have then the flexibility to determine when 2 actions are the same, both plain objects and thunks. Basically providing your own getSimilarActionsInQueue

export default function createReduxStore() {
  const networkMiddleware = createNetworkMiddleware({
    comparisonFn: (action, queue) => { ... // do your comparision }
  });

  const sagaMiddleware = createSagaMiddleware();

  const rootReducer = combineReducers({
    foo,
    bar,
  });

  const middlewares = [networkMiddleware];

  const store = createStore(rootReducer, applyMiddleware(...middlewares));
}
posted by rgommezz over 5 years ago

@rgommezz would you recommend passing the comparison function into the reducer? So in handleOfflineAction this check for which comparison function will be done.

    const similarActionQueued = comparisonFn
      ? comparisonFn(actionWithMetaData, state.actionQueue)
      : getSimilarActionInQueue(actionWithMetaData, state.actionQueue);
posted by LiquidSean over 5 years ago

Yes, that sounds good!

Let's create a factory function and export it as the new API for the networkReducer.

// configureStore.js
import { createStore, combineReducers } from 'redux'
import { createReducer as createNetworkReducer } from 'react-native-offline';

const rootReducer = combineReducers({
  // ... your other reducers here ...
  network: createNetworkReducer(comparisonFn),
});

const store = createStore(rootReducer);
export default store;

Then inside the reducer we'll pass that function along to the handler:

const createReducer = (comparisonFn = getSimilarActionInQueue) =>
 (state: NetworkState = initialState, action: *) => {
  switch (action.type) {
    case actionTypes.CONNECTION_CHANGE:
      return {
        ...state,
        isConnected: action.payload,
      };
    case actionTypes.FETCH_OFFLINE_MODE:
      return handleOfflineAction(state, action, comparisonFn); // <= new arg here
    case actionTypes.REMOVE_FROM_ACTION_QUEUE:
      return handleRemoveActionFromQueue(state, action.payload);
    case actionTypes.DISMISS_ACTIONS_FROM_QUEUE:
      return handleDismissActionsFromQueue(state, action.payload);
    default:
      return state;
  }
}

What do you think?

posted by rgommezz over 5 years ago

@rgommezz I like that idea. I will try and start working on this.

posted by LiquidSean over 5 years ago

@issuehunt has funded $100.00 to this issue.


posted by issuehunt-app[bot] over 5 years ago

Is this issue still open?

posted by kodeGenius over 5 years ago

When are you guys planning to merge #208 to fix this issue?

posted by nerdomancer over 5 years ago

@rgommezz has rewarded $70.00 to @liquidsean. See it on IssueHunt

  • :moneybag: Total deposit: $100.00
  • :tada: Repository reward(20%): $20.00
  • :wrench: Service fee(10%): $10.00
posted by issuehunt-app[bot] over 5 years ago

@all-contributors please add @LiquidSean for code and doc

posted by rgommezz over 5 years ago

@rgommezz

I've put up a pull request to add @LiquidSean! :tada:

posted by allcontributors[bot] over 5 years ago
posted by rgommezz over 5 years ago

If I understood right, its only possible to delete 1 item off the action Queue, would it be possible to allow an array of actions to remove.

For Example in Action Queue:

SAVE_TODO_ITEM DELETE_TODO_ITEM

You could of course leave it in the action Queue and there will be no bugs, but I would prefer to not send it to the backend at all.

For now I can only find one Action and delete it from the Queue, I tried to return an array but that doesnt work either.

Is it currently possible to delete multiple items, or is there another feature for it?

Thank you in Advance :)

posted by Relentl3zz about 4 years ago

Fund this Issue

$100.00
Rewarded

Rewarded pull request

Recent activities

liquidsean was rewarded by rgommezz for rgommezz/react-native-offline# 206
over 5 years ago