Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the proper way of connecting firebase with redux-sagas?

I am building react-native app, where I use react-native-firebase and redux-saga. This is my first project using redux-saga, hence I am learning. So far I got the authentication of the user using the following:

import firebase from 'react-native-firebase';

function* loginEmlPwdSaga(action) {
  try {
    const auth = firebase.auth();
    const data = yield call(
      [auth, auth.signInAndRetrieveDataWithEmailAndPassword],
      action.email,
      action.password,
    );
    yield put(loginSuccess(data));
  } catch (error) {
    yield put(loginFail(error));
  }
}

However, now I am stuck at the point, where I want to subscribe to the collection. In react-native-firebase I would use the following:

firebase.firestore().collection('users').onSnapshot(...)

I am not sure what is the best approach to handle subscribes in redux-saga. Can you show me the pattern that I can use for the future usage of onSnapshots (testable one)?

like image 850
uksz Avatar asked Jun 03 '18 17:06

uksz


People also ask

How do Redux sagas work?

Redux Saga is a middleware library used to capture the action from the Redux and interact with external services (API) outside asynchronously and communicate with the Redux store. This includes making HTTP requests to external services, accessing browser storage, and executing I/O operations.

What are Redux sagas?

redux-saga is a library that aims to make application side effects (i.e. asynchronous things like data fetching and impure things like accessing the browser cache) easier to manage, more efficient to execute, easy to test, and better at handling failures.


1 Answers

The easiest way to subscribe to a firestore collection using redux-saga is to use a channel:

function * syncUsers () {
  const ref = app.firestore().collection('users')
  const channel = eventChannel(emit => ref.onSnapshot(emit))

  try {
    while (true) {
      const data = yield take(channel)
      yield put(successAction(data))
    }
  } catch (err) {
    yield put(errorAction(err))
  }
}

This will dispatch an action (created by successAction(data)) every time the firebase pushes a change to your client.

You can also use a library like redux-saga-firebase to automate this part and simply use:

function * syncUsers () {
  yield fork(rsf.firestore.syncCollection, 'users', {
    successActionCreator: successAction,
    failureActionCreator: errorAction
  })
}

Disclaimer: I'm the author of redux-saga-firebase.

UPDATE: redux-saga-firebase is no longer maintained and is not compatible with Firebase 8.

like image 91
n6g7 Avatar answered Oct 14 '22 20:10

n6g7