prescottprue / react-redux-firebase

Redux bindings for Firebase. Includes React Hooks and Higher Order Components.
https://react-redux-firebase.com
MIT License
2.55k stars 559 forks source link

question(query): Scaleable decoupled patterns #417

Open Floriferous opened 6 years ago

Floriferous commented 6 years ago

In my thunks where I somehow access the database, I always have to extract firebase first, before injecting it inside a module that should hide firebase as much as possible:

// addTodo module handles all the firebase specific issues, errors, subcollections, etc.
import addTodo from '.../api/addTodo';

export const insertProduct = values => (
  dispatch,
  getState,
  { getFirestore },
) => {
  const { add } = getFirestore();

  return addTodo(add, { otherParameters })
};

Is there a way to write these more like this, and remove all the firebase access from thunks? :

import addTodo from '.../api';

export const insertProduct = values => (
  dispatch,
  getState,
) => {
  // Nice abstraction around firebase/firestore
  // Magically adds a todo to firebase without this action knowing about firebase
  return addTodo({ otherParameters })
};
prescottprue commented 6 years ago

@Floriferous dispatching actions that in turn call promises and dispatch other actions is not yet supported, but the middleware to do this is already under way within redux-firestore (though it is not yet finished or documented).

The documentation is going to look something like the following (note that none of the provided examples will work yet since this has not been released):

Planned Future Docs Sample

Middleware

redux-firestore's enhancer offers a new middleware setup that was not offered in react-redux-firebase (but will eventually be ported) Note: This syntax is just a sample and is not currently released

Setup

Still undermined - could be included with reduxFirestore store enhancer or may need to be added separately as its own reduxFirestoreAsyncMiddleware (or a similar name)

Usage

Direct Dispatch

import { FIREBASE_CALL } from 'react-redux-firebase'

dispatch({
  type: FIREBASE_CALL,
  collection: 'users', // only used when namespace is firestore
  method:  'push' // get method
  args: [{ newData: 'test' }]
})

Action Creator

import { actionCreators } from 'react-redux-firebase'

dispatch(actionCreators.push({ collection: 'users' }, { newData: 'test' }))

Some of the goals behind this approach include:

  1. Not needing to pass around a Firebase instance (with react-redux-firebase this means using getFirebase and/or firebaseConnect/withFirebase HOCs)
  2. Business logic can be less aware of data layer provider (Firebase) - the point you are noting
  3. Follows patterns outlined in the redux docs for data fetching
  4. Easier to expand/change internal API as Firebase/Firestore API grows & changes