I'm writing my first redux application and have run into an issue.
Say I have a basic todo application - a reducer provides an array of todos. The view is a series of tabs with each todo's header on it. You can select a tab and that todo's edit view will appear below.
My first approach was to create another reducer that tracks the selected tab's ID (as "selected todo" in this case is UI state, I don't want to put it in the todo reducer's state). The reducer receives a "SELECT_TODO" action with the ID attached and updates accordingly. Then the view can render the tabs and the selected todo's edit view below. Pretty straightforward. A new todo could be selected automatically by the reducer listening for an ADD_TODO action and returning its ID.
What I'm stuck on is how to handle the user deleting the selected todo and having a new selected todo calculated automatically - I can have the "selected todo" reducer listen to a REMOVE_TODO action,
but in order to calculate a new value it needs access to the list of todos - it will try to select the next todo,
or the previous if the selected todo is at the end of the list.
Any suggestions on how to best structure things in this scenario? Since I'm new to redux it would be really helpful to get some advice - I have a few ideas that would technically work but I'm not sure if I'm on the right track or not.
Thanks.
I would handle this in an action creator using redux-thunk. You will have access to the whole state in your action creator. This allows you to either
a) fire two actions, one for removing one for setting the new selected id
b) fire a single action for removing with a new selected in in the payload.
In both cases you can randomly select a new item from your state in the action creator.
Thanks @johanneslumpe. I haven't been using redux-thunk, but when I read your answer mention using two actions I realised my real issue may actually be in the action creator stage - my actions are not passing all of the data the reducers require.
I can pass the existing list of todos to my add/remove todo action creators - it makes sense to me that a reducer would need to know where this data will ultimately be removed from or added to in order to calculate its result.
It does mean every add/remove todo view requires the current list of todos, but at least it's explicit where the data came from.
I can pass the existing list of todos to my add/remove todo action creators - it makes sense to me that a reducer would need to know where this data will ultimately be removed from or added to in order to calculate its result.
It’s best if you avoid passing large pieces of state as part of the actions. This creates a sort of “feedback loop” where it’s hard to trace where the data is coming from in case there is a mistake.
I think that REMOVE_TODO including nextSelectedId is a good compromise. You let the view calculate it, and the view knows which one should be selected. For example, the view might apply some sorting or filtering to the results, so in this case in particular the view knows which one is to be selected better than the reducers can.
Thank you @gaearon, that makes perfect sense.
I have a problem with a diferent kind of dependency:
I'm creating a hamburgers delivery shop.
In the shop I have ingredients and meals (meal consist of ingredients).
Every ingredient has a unique id.
A meal instance contains a list of ingredients ids (the ingredients it contains).
Therefore - I want to load the ingredients details before I load the meals (so I don't have problems when I try to display the meals at the menu page).
I need a way to fire LOAD_MEALS only after the ingredients reducer is done.
(dispatching LOAD_INGREDIENTS before dispatching LOAD_MEALS doesn't solve the problem because loading the ingredients might take longer than loading the meals).
How can I solve this problem?
@ELIYAHUT123 : That's a usage question, and should really be asked on Stack Overflow instead of this issues tracker.
That said, it sounds like you may be a bit confused. The reducer function call is 100% synchronous, so saying "the ingredients reducer is done" doesn't make sense. I _think_ what you mean is "after the ingredients have been loaded from the server".
But yeah, ask that on SO - you'll get more attention and a better response than here.
@markerikson: Maybe I wasn't clear enought.
I'll explain:
For reasons of efficiency I fetch all the data (the ingredients and the meals) together from the server.
If I were to dispatch FETCH_ALL_DATA and let both the ingredients and the meals redcers "listen" to this action (and update the store asynchronously) - I would run into problems when trying to display a meal that its ingredients are not loaded to the store yet (that's what I ment when I wrote "the ingredients reducer is done" - done loading the fetched ingredients to the store).
I will try SO as well, I just saw the title of this issue and thought my question is suitable.
Here is a link to the question on SO:
http://stackoverflow.com/questions/39379539/react-redux-manage-dependencies-between-reducers