Reputation: 8340
I am using redux, react, react-router and reselect. There is a screen that contains two components, the Header
and the Body
. There is a component in the Header
to select an ID. When a new ID is selected a new action is dispatched to update the ID in the state in redux.
Based on that ID there should be an asynchronous API call to load the element from the server and store it in the state, which should then trigger a render of the screen and display the element in the Body
. The loaded element would then be extracted from the state with reselect.
The real-life scenario is a bit more complex than that, because there are many different Body
components with different API calls and only one Header
component. But they can be treated as different screens. So, for example:
Screen 1:
components: Header
, BodyTypeA
; API to call: apiA
Screen 2:
components: Header
, BodyTypeB
; API to call: apiB
My understanding is that the API call should be done in the reducer when it stores the new ID in the state. But how to determine which screen is being shown and which API to call if the action is dispatched by a component shared across screens? Can I somehow subscribe in the Body
to changes to the ID and trigger the API call from within the screen? The screen type is determined by the react-router. Would the reducer have any access to the router to determine which screen is being shown? Are there any best practices for handling such a scenario?
Upvotes: 1
Views: 150
Reputation: 16971
Seems like you may be overthinking this. So, one thing at a time:
My understanding is that the API call should be done in the reducer when it stores the new ID in the state.
Unless you'll be using redux-loop that allows returning an action from a reducer you're wrong. In principal reducers CAN NOT dispatch any actions, they only consume them. It's the middleware layer (or action creator) where you dispatch your actions and may call your APIs.
But how to determine which screen is being shown and which API to call if the action is dispatched by a component shared across screens?
To determine "where you are" it's best to keep routing information in your state tree. Since you're using react router anyway consider using https://github.com/reactjs/react-router-redux to expose route information in your state tree and then access it from your middleware / action creators / selectors.
Can I somehow subscribe in the Body to changes to the ID and trigger the API call from within the screen?
Yes, technically you can subscribe to store changes, but normally you wouldn't have too - see my other points and hopefully it's clear enough.
The screen type is determined by the react-router. Would the reducer have any access to the router to determine which screen is being shown?
No (in general) reducers only have access to their slice of state, so while your reducer may react to react router actions (if you'll use react-router-redux - see above) to store route details you require, but in principle it should be up to your selectors and/or connected components to construct / pull data required for given component from the state tree.
Are there any best practices for handling such a scenario?
I guess use react-router-redux, introduce a middleware that will trigger an API call in response to your action and will dispatch consecutive action containing data returned from the API. That action you'll handle in your reducer, storing data in the tree.
And a random tip, if you have components like bodyTypeA, bodyTypeB then those components can (should even) keep information if they're A or B and propagate that to the action creator. E.g. if you have an action creator called requestForId(ID) you'd modify signature to be requestForId(ID, type) and in your component / callback (whenever you're invoking that action creator) you'd be passing not only the ID but also the type, i.e. bodyTypeA would call it with requestForId(ID, 'A').
Upvotes: 2