How to call yield in firebase read API
Asked Answered
F

1

5

I have a redux saga API, where by I am connecting to firebase and reading records of data.

var roomRef = firebase.database().ref('/Users/' + userid + '/rooms')
  var rooms = []
  roomRef.once('value', function (snap) {
    var roomkeys = snap.val()
    for (var roomkey in roomkeys) {
      firebase.database().ref('/Rooms/' + roomkey).once('value', function (item) {
        rooms.push(item.val())
      })
    }
    console.log(rooms)
   --> put({type: 'LOAD_ROOMS', payload: { rooms: rooms}})
  })

Since my put is inside a callback function I cannot use the yield keyword. How do I dispatch an event to change the state of my reducer with the new values 'rooms'

Ferrick answered 11/2, 2017 at 23:53 Comment(0)
S
7

The way to work around this is to convert the callback into a promise. redux-saga knows how to resolve promises that you pass to the call effect. But call takes a function, not a promise. From the docs:

If the result is a Promise, the middleware will suspend the Generator until the Promise is resolved, in which case the Generator is resumed with the resolved value. or until the Promise is rejected, in which case an error is thrown inside the Generator.

var roomRef = firebase.database().ref('/Users/' + userid + '/rooms')
var rooms = yield call(function() {
  return new Promise(function(resolve, reject) {
    roomRef.once('value', function (snap) {
      var rooms = []
      var roomkeys = snap.val()
      for (var roomkey in roomkeys) {
        firebase.database().ref('/Rooms/' + roomkey).once('value', function (item) {
          rooms.push(item.val())
        })
      }
      resolve(rooms)
    })
  })
})
yield put({type: 'LOAD_ROOMS', payload: { rooms: rooms}})
Scorify answered 15/2, 2017 at 18:39 Comment(2)
In this case, you don't even have to instantiate a Promise yourself, as firebase's once method already returns a Promise. If you have a function like: function getRooms(userId){ return firebase.database().ref('users/' + userId + '/rooms').once('value').then( snap => snap.val() ) }, you can then const rooms = yield call(getRooms, userId)Kimberykimble
Your var rooms is what you resolve and an array that you put in the yield? Is it correct that they're all named the same? If so, why? Does it only work because of the local scope of rooms array?Keniakenilworth

© 2022 - 2024 — McMap. All rights reserved.