Redux: Is there any smart way to avoid the antipattern of importing store for helper files?

908 Views Asked by At

I'm currently build a React Native application using Redux the state management and Firebase Cloud Messaging for my real time communication.

To use FCM in the background on Android you are required to create file called bgMessaging.js.

// @flow
import firebase from 'react-native-firebase';
// Optional flow type
import type { RemoteMessage } from 'react-native-firebase';

export default async (message: RemoteMessage) => {
    // handle your message

    return Promise.resolve();
}

My problem is that I need to dispatch an action here. The only solution I found for this was to import my store and call store.dispatch(). I've been told this is an anti-pattern and considered bad practice. What else could I do that is not an anti-pattern?

Edit: Mark Erikson himself was so kind and gave his opinion on this topic. Thanks Mark!

2

There are 2 best solutions below

0
On BEST ANSWER

I've also come into the same scenario when writing my application. My approach to my React Native App was to create React Components, but deal with a lot of my data fetching/handling outside of React Components - because I didn't know whether I'd be using React all of the time, but wanted to create re-usable modules for my other Type/JavaScript projects. For example I'd created a few helper files which dealt with various APIs, but when I integrated Redux into my project - I had the same issue. How do I dispatch without re-adding in your store (as I can see this can be considered Anti-Pattern).

Reading into a few articles, there's no real place to suggest that this approach is 'Anti Pattern'. A lot of the time, stores are imported within the React Context (which is doesn't need to be) - this is Anti Pattern. In your use case, I don't really see how that can be Anti Pattern, I certainly came to this conclusion when I was doing the same thing. In my view 'Common' parts of the app should be used by many other parts of the application.

0
On

What I'm seeing is that you need to provide a function which has a single arg, typed as RemoteMessage which returns a promise, and you need to provide that function to registerHeadlessTask (wrapped in another function for some reason..)

So what if your bgMessaging file looked like this..

// @flow
import firebase from 'react-native-firebase';
// Optional flow type
import type { RemoteMessage } from 'react-native-firebase';

export default store => {
  return async (message: RemoteMessage) => {
    // handle your message
    store.dispatch();
    return Promise.resolve();
  }
}

and in your index you did..

import bgMessaging from './src/bgMessaging';

const store = redux.createStore();

const bgMessagingFn = bgMessaging(store);

// Current main application
AppRegistry.registerComponent('ReactNativeFirebaseDemo', () => bootstrap);
// New task registration
AppRegistry.registerHeadlessTask('RNFirebaseBackgroundMessage', () => bgMessagingFn);