1

I'm new to React, React Native and Redux so I'm trying to wrap my head around alot of these news concepts for the past few days.

One problem I ran into right now is computing new data in Action Creator, before wrapping it around action object and passing into reducer, that requires a piece of data from other branch within the state tree. How would you normally go about solving this? Changing the structure of the global state tree or map this piece of data to the component requiring it?

Given the state tree:

{
    ListView:{
        dataSource : a ListView.DataSource type
    }
    SubmitForm:{
        title : 'name of title',
        text : 'description'
    }
    isFetchingData: true/false
}

And supposedly, each branch is handled by a different reducer, and each branch's data is passed into separate component as props.

Here's the scenario (I'm translating the React tutorial to React Native using Redux ):

  1. Submit button is clicked in the SubmitForm
  2. --> dispatch an action to notify store that data is being sent, then async grab and send {title,text} to API server.
  3. Upon success ---> compute the dataSource returned from API server and pass the result dataSource to reducer (according to the tutorial). And by computing dataSource, I mean dataSource.cloneWithRows(....) (explained here), which requires the dataSource from ListView as seen above.

So my thought was the Form component should not have a prop called dataSource, as this is from another branch in the state tree. But without it, I'm not sure how to achieve the desired dataSource. Changing (merging ListView and SubmitForm in this case) the structure of the state tree would also be strange, as to my understanding about Redux pattern. So could someone help me figure this out? Thanks

Glorfindel
  • 21,988
  • 13
  • 81
  • 109
rustyengineer
  • 343
  • 3
  • 16

3 Answers3

2

Thanks guys. I think I found the best solution by using redux-thunk (well I was actually using redux-thunk to handle async action, but didnt read up the api well enough). Basically the thunk is also injected with getState, so basically calling getState() will gain me access to the global state tree and that should solve my problem.

const actionCreator = (args) => {
    return (dispatch,getState) => {
        // dispatch action to notify store that data is being sent
        fetch(url)
        .then((response) => response.json())
        .then((resData) => {
            // dispatch action to notify data received
            // compute new data using resData and current dataSource accessed by getState().ListView.dataSource
        })
    }    
}
rustyengineer
  • 343
  • 3
  • 16
1

I have thought this problem before and I think this may be a way.

For example. You have actionA,reducerA and branchA of store. You have actionB,reducerB and branchB of store.

Now you want to read branchA and branchB at the same time and change them.

Ok,let us define two actions.

One in actionA(sub-actionA), which to change the branchA. Another in actionB(sub-actionB), which to change the branchB.

And then, define a total action(total-action),which will call sub-actionA and sub-actionB in order.

The last problem is "How to read branchB in the sub-actionA".

ok, we can use the method 'getState' of store. We import the store into the actionA, and call store.getState() It will return the whole tree of store.

youngwind
  • 475
  • 4
  • 5
  • I'm not entirely sure I understand your point. From what I see, you basically pass the data from the other branch to the exclusive component requiring it (you pass the entire store's state in this case), which is what I already suggest as one of my solutions above. This is going back to my original question: is this a healthy practice or is it anti-redux? Also, if we go down this road, I believe we don't even need to call store.getState() if we use connect() API to map state's data and dispatch as props to component, since the store's state is already passed in as argument in mapStateToProps – rustyengineer Apr 10 '16 at 16:10
  • My point is the third method in the above question's link. Yes, you are right. You can pass on the data through connect and props to action directly, this is another way. @rustyengineer – youngwind Apr 11 '16 at 00:37
1

This is a common question, and conveniently has an answer over in the Redux FAQ.

Short version: combineReducers solves a simple use case of splitting reducer functionality by domain/slice-of-state. You've gone past that, and now need to either add custom additional top-level reducer logic to handle this action, or include the additional needed data in the action itself.

Edgar
  • 6,022
  • 8
  • 33
  • 66
markerikson
  • 63,178
  • 10
  • 141
  • 157