rmrs / react-native-redux-saga-firebase-patterns

37 stars 6 forks source link

Any runnable example application? #1

Open ghost opened 6 years ago

ghost commented 6 years ago

Hi there, i like your suggested patterns, bundling react-native, redux-saga and firebase together. My aim is to understand the 'whole thing' and figure out, how these patterns work in a runnable application. Is there any example of how to use/call the redux-actions/-sagas in a react-native component? what about calls that depend on each other? how do i call them?

omer88 commented 6 years ago

Hi @ralcon, Thanks! The whole idea is not to mess with async stuff with the component. So all you have to do in the components is to call an action (you don't call a saga - it responses to actions).

Let's look at the example in this repo: Say you want to update user contact while pressing a button. We've already prepared an action creator named updateUserContactsRequested (at actions.js file). All you have to do in your component is to map that action to props and connect it to react-redux (as usual in redux) and then call this prop with appropriate parameters when you press the button. In our case it would look like this: this.props.updateUserContactsRequested(this.props.uid, 'contactUid', this.props.username, this.props.userPhone) In order to load the user contacts and initialize the listener, you just have to call listenToUserContacts(this.props.uid) in the componentDidMount lifecycle method. Note: I assumed that in your props you have uid, username and phone, which were probably mapped from redux state.

Regarding calls that depend on each other - what do you exactly mean? can you give an example?

ghost commented 6 years ago

Hi @omer88, loading main data is easy with this pattern (like you mentioned). First, for example, let's say, we have following data structure in a firebase database:

tasks
  |-- taskOneId
  |    |-- name: My first Task
  |    |-- completed: false
  |    |-- participants
  |        |-- firstParticipantId
  |        |-- secondParticipantId
  |        |-- thirdParticipantId
  |-- taskTwoId
       |-- ...
participants
  |-- firstParticipantId
  |    |-- part_completed: false
  |    |-- user: firstUserId
  |-- secondParticipantId
  |    |-- part_completed: false
  |    |-- user: firstUserId
  |-- thirdParticipantId
  |    |-- part_completed: false
  |    |-- user: firstUserId
  |-- fourthParticipantId
       |-- ...
users
  |-- firstUserId
  |    |-- name: Leonardo
  |    |-- age: 13
  |-- secondUserId
  |    |--name: Donatello
  |    |-- age: 22
  |-- thirdUserId
  |    |--name: Michaelangelo
  |    |-- age: 21
  |-- fourthUserId
       |-- ...

Second, let's say we got a list of taskIds, where i am involved in. In the data structure, it is only taskOneId and my userId is firstUserId. My goal is to have a query (and data) for all participans of taskOneId and the inherent user! So i query the data like this:

// ----- saga_registration.js -----
export default function* rootSaga() {
  yield all([
    sagas.watchListener(metaTypes.tasks),
    sagas.watchListener(metaTypes.participants),
    sagas.watchListener(metaTypes.users)
  ])
}
// ----- actions.js -----
export function listenToTasks() {
  const ref = firebase.database().ref('tasks')
  return firebaseListenRequested(ref, metaTypes.tasks)
}
// ----- MyTasksMask.js => React.Component -----
class MyTasks extends React.Component {
    componentDidMount() {
        this.props.getTasks()
    }
    ....
}
export default connect(
    // MAP_STATE_TO_PROPS
    (state, props) => { ... },
    // MAP_DISPATCH_TO_PROPS
    (dispatch) => {return {getTasks: () => {return dispatch(listenToTasks())}}}
)(MyTasks)

With this, i got my listener installed and receive task data. Now i want to iterate through the participants, register the listener and receive participants data for every participant item. The same with users data.

Lets describe it in plain text: Receive the tasks, where i am involved to (by ID). Get all participants of the tasks, where i am involved to and query and receive user data of the users in participants.

A little bit clearer? How do i get this work in only one React.Component?

ghost commented 6 years ago

I think the propblem is to identify, when the previous request is loaded!?

ghost commented 6 years ago

Maybe, my expected state result is the best description. I expect my state to be...

state.firebase: Object
  |-- users: Object
  |    |-- error: ""
  |    |-- inProgress: false
  |    |-- items: Object
  |        |-- firstUserId:Object
  |        |   |-- name: Leonardo
  |        |   |-- age: 13
  |        |-- secondUserId:Object
  |        |   |-- name: Donatello
  |        |   |-- age: 22
  |        |-- thirdUserId:Object
  |            |-- name: Michaelangelo
  |            |-- age: 21
  |-- participants: Object
  |    |-- error: ""
  |    |-- inProgress: false
  |    |-- items: Object
  |        |-- firstParticipantId:Object
  |        |   |-- part_completed: false
  |        |   |-- user: firstUserId
  |        |-- secondParticipantId:Object
  |        |   |-- part_completed: false
  |        |   |-- user: secondUserId
  |        |-- thirdParticipantId:Object
  |            |-- part_completed: false
  |            |-- user: thirdUserId
  |-- tasks: Object
       |-- error: ""
       |-- inProgress: false
       |-- items: Object
           |-- taskOneId:Object
               |-- name: My first Task
               |-- completed: false
               |-- participants: Object
                   |-- firstParticipantId
                   |-- secondParticipantId
                   |-- thirdParticipantId