Where should you put the API-calls in Redux?
I think they belong in Actions because they are part of the data and don't have side-effects.
Does that sound right?
I want to avoid RxJS or ReduxSaga.
I make my API calls in my action file but have a separate function that creates the action itself. Regardless I am agreeing with you in that API Calls work best (in our collective opinion) alongside action creators.
Create Scenarios
If you call a synchronous API just in a single component, you can make your API call in actions, get the data back, and then dispatch. Simple is that.
If you call a synchronous API in multiple components, You will handle them all separately?
If you call a asynchronous API, You will dispatch a flag when the request began and again dispatch a flag when request complete?
For point 2,3 Thunk middleware is the best option as it is much easier than Saga.
This is a can of worms in the redux world and there are many approaches. The main idea is to execute functions that have access to the store’s dispatch method so that these functions can orchestrate their own sequence of actions to the store. However, each approach dresses up the function execution and the inherent statefulness of side effects (e.g. waiting for an API call to finish before dispatching the “done” action to the store) in a different way:
The imperative solution is thunks which are just plain old functions. When the store receives a thunk, instead of running the thunk through the reducer like a regular object action, the store executes the thunk while passing the store’s dispatch function so that the thunk can orchestrate its own sequence of actions. See redux-thunk for an example.
redux-saga is a declarative solution where you dispatch action objects that describe how the side effect is to be carried out. For example, if the side effect is fetching from an API then the action contains the fetch function and the arguments to be passed to the fetch function. For example, if the fetch call is fetchFromServer(a, b, c) then the action you dispatch contains fetchFromServer, a, b and c. The stateful part of the side effects is kept inside generator functions called “sagas”.
redux-observable is another declarative solution but instead of using generators for “statefulness”, it uses observables. Observables can be a bit non-intuitive so I won’t go much into it here but it is the solution that I used. Honestly, the latter two are, to some extent, two sides of the same coin but I find observables a more elegant abstraction.
Related
What is the best practice for deriving data in componentDidUpdate, pushing that into the redux store, but also then using that data to further derive more data, and again push that into the redux store?
Given redux is synchronous, I was hoping to be able to access the updated store straight after I done the dispatch, but I am assuming that because it is still within the componentDidUpdate, props would not have been updated with the new store data via mapStateToProps. i.e. I tried -
componentDidUpdate(){
this.determineAndStoreA()
this.doSomethingElse(this.props.A) // hoping this would be the updated A
}
this.props.A is the old value still
should I being something more like -
componentDidUpdate(){
const a = this.determineA()
this.storeA(a);
this.doSomethingElse(a) // using a local copy of A
}
With some further digging, I found a similar question in https://github.com/reduxjs/react-redux/issues/291 . Dan recommends to react to the action in the reducer, but that feels like I now have to combine the logic of determining A, determining B from A, storing A and B at same time?
I think I see what you are struggling with. First let me try to describe more fully the scenario I think you are dealing with.
You have A and B in your store. C is derived from A and B, so if A changes, you want to re-derive C and put it in your store. You could then have component prop E that is derived from C and D. Action x changes A and now you need the new value for C or E and it is difficult to do it in one step without making the reducers overly complicated.
There are three main approaches I have used for scenarios like this and which one I would recommend depends on the specifics of the scenario. All of these are just different approaches for how/when/where to determine C (and could be extended to further derivations like E).
Approach 1
Calculate C in middleware designed for dealing with side effects of actions.
This is the approach most similar to what you already have. It just moves it out of a component so you aren't fighting against the interaction between your store and when lifecycle methods receive the new information. For this approach, I would use Redux Saga and have it handle calculating C in response to action x and dispatching the action to update the store with the new value for C. It's easy to do this (if you're past the initial Redux Saga learning curve) since Redux Saga receives the action after the store has already been updated. The main downside of this approach is that your store will temporarily be in an inconsistent state where C doesn't yet reflect the change to A. For some scenarios this matters and for some it doesn't. The other potential downside is that if you aren't already using Redux Saga, it can be a little intimidating at first because the use of generator functions and yield and the whole mindset when using Redux Saga can feel a bit alien (but I really love using Redux Saga for complex async scenarios).
Approach 2 Calculate C in an action creator.
This generally involves using a thunk for the initial response to action x and the thunk can then get B from the store, calculate C and dispatch an action with a payload that contains two pieces -- one used by the reducer for A and one used by the reducer for C. The main downside with this approach is if there are multiple ways that the dependencies for C (i.e. A and B) can change, this can become a complicated way to organize things, but for some scenarios it can work fine. I have mostly moved away from this approach in favor of the other two approaches.
Approach 3 Don't put C in your store.
If C is fully derived from other things in your store, then it doesn't really need to be in the store. C is just a view on other information in your store. You can use a selector for this purpose instead. If it is expensive to derive C, then use a memoized selector. In the more complicated case of also having E that is derived from C and D, a selector for E can leverage the selector for C while getting D from the store. This is the approach I generally favor unless there is a compelling reason for C to be in the store. This approach allows your reducers to stay simple and independent while keeping your store in a consistent state.
Other Approaches
There are other ways to do this, but the 3 approaches above are ones I have actually used myself. One other route is to have a reducer that leverages other reducers. In this approach, the reducers for A and B would be used by a reducer that then computes C and returns state with all three pieces of information. There are packages out there for making it easier to compose reducers in this manner, but I haven't used them because I'm not very interested in this approach. For me, it just feels like the wrong place to put this complexity.
You won't get the updated prop in the same cycle as Redux pushes the value in to the store and triggers another update to the component.
Do you really need to trigger both actions from componentDidUpdate?
What you can do is create a new action that is triggered from the action where you stored your A value.
something like this
store.dispatch(saveValueA()).then(() =>
doSomeAction()
);
Your component will be rerender everytimes A would change, and componentDidUpdate will be called.
You can then do something like :
componentDidUpdate(prevProps){
const hasAChanged = this.props.A !=== prevprops.A;
if (hasAChanged) {
this.determineAndStoreA()
} else {
this.doSomethingElse(this.props.A)
}
}
I'm not sure what you'r trying to do, hope it helps.
Question about Redux data flow.
Let's talk about huge enterprice application. Dozens of modules, complex hierarchy of reducers, hundreds of action-types.
Simple flow:
Control dispatches an action(for example, input - typing). This action go through every reducer, go through hundreds of switch-cases, and new state is merged from all of reducers with minimal changes. I think, that we have huge unnecessary overhead in this scenario.
What options we can use to decrease overhead?
Use isolated high-level sub-apps with their own provider.
This option will decrease overheads. But if we need any common features in sub-apps, like account info/notifications/etc, we should duplicate it.
Use asyncReducers for code-splitting.
This option, also will decrease overheads, but it is not recommended.
Make a reducers with action-filters. In this case, we add additional information to each action, which reducer should process it.
This option also decrease number of swithces and complexity of newState merging.
But in option 3 I can't understand one thing.
We have control, which is connected to concrete part of state.
99% of actions are processed by single reducer.
Each action at reducer is processed by "case function", which is moved to separate logic-module.
We have action-creator which knows concrete reducer which process this action, and has access to global state.
Why action-creator should dispatch global action, which then will filtrated by cascade of reducers, and then will be swithed through dozens of cases, with not optimal merging of new global state?
Why can't we call case-function in action-creator, compute new global state in optimal way and dispatch it as payload with "SET_GLOBAL_STATE" action type?
I understand that it is anti-pattern. But i can't understand what we lose in this case.
I'll be glad, if someone will explain me what is wrong.
Several thoughts here.
First, per the Redux FAQ entry on splitting logic between action creators and reducers, it's up to you where to put the bulk of your logic. If you prefer to do the actual calculations for what a piece of the new state should be in an action creator, and just have a given slice reducer do return {...state, ...action.payload}, you can.
Second, per the Redux FAQ entry on the performance of calling reducer functions, the cost of calling many reducer functions will generally be very minimal, since most of them will just check the action type and return their existing slice of state. So, the reducer logic will rarely be a performance bottleneck.
Third: yes, it's entirely possible to calculate the entire new app state in an action creator, and have a single generic "SET_GLOBAL_STATE" action. This will allow use of Redux's middleware and time travel debugging, etc. However, this also throws away many of the possible benefits and use cases for Redux. I discussed a lot of the intended purpose for Redux in my blog posts The Tao of Redux, Part 1 - Implementation and Intent and The Tao of Redux, Part 2 - Practice and Philosophy.
To summarize the reasons why we discourage the idea your describing: Redux is intended to make it easy to trace when, why, and how a certain piece of state was updated. While it's up to you to decide how granular you want your actions to be, ideally they should be semantically meaningful. That way, when you read the action history log, you can actually understand the sequence of actions that were dispatched. Also, if you search for a given action type, you should be able to quickly narrow down exactly where in the codebase that action is used. If you only have a single "SET_GLOBAL_STATE" action, it will be almost impossible to determine what part of the code caused a given state update.
I'm developing an application that has several states (reducers). Let's say they are messages, likes, comments (all of them are from the completely different instances so i'm not sure if i should combine them into one state).
Every 30 seconds i make request to the server and i receive response that says which parts of my application have been updated. E.g. i received new messages or new comment.
I don't really know how to handle those responses. First, i can simply let container update all other states, but i don't think that it's a good idea, because every container should have it's own state.
Second, i can create a middleware that will catch every action, find the one with required information and shot another action (e.g. new message). After that reducer of the messages will catch this action. But i'm not sure again if this is a correct approach for two reasons:
Is it okay to shot actions from the middleware (won't it be a bidirectional flow)?
How can i actually do it?
Thanks in advance.
UPD. I did it using middleware, but i'm still not sure if this is a correct way. In my middleware i obtain required data using store.getState()... and then i make store.dispatch(myAction). Is it okay?
It's important to understand that a reducer /= state. ( reducer not equal state )
You should have one state, one store for your application. Use combineReducers to well.. combine reducers to keep everything in one state.
http://redux.js.org/docs/api/combineReducers.html
You need to handle async behaviour, something which is not default by redux and therefore you have to use some kind of middleware - meaning you were on the right track.
Try and use the more common once like:
https://github.com/gaearon/redux-thunk
https://github.com/redux-saga/redux-saga
It's advised to separate the async logic from your app. Meaning you need to init your async calling in the app, but keep the async logic in the store.
Here's a guide by Dan Abramov and Redux-Thunk which is simple and clear:
http://redux.js.org/docs/advanced/AsyncActions.html
Hope it answers you.
I think there are three options:
The UI Component calls two ActionCreator methods. Each ActionCreator dispatches a message.
The UI Component calls one ActionCreator method which dispatches a message and calls another ActionCreator method.
The UI Component calls one ActionCreator method which does not dispatch any message, but calls two other ActionCreator methods which each dispatch their own message.
Is there a reason to prefer one of these options over the others? Is there any other option?
This is setter-thinking, and is not the correct way to be thinking about Actions. Actions inform your application, they do not cause side effects.
Stores are in control of your application. They are where all logic resides. Stores cause side effects in response to the information they receive from actions. Actions are like a newspaper. Stores respond to the news.
Actions describe something that happened in the real world. In this case, the user did something. It could instead be that the server responded with some data, or that the browser completed an animation frame. Regardless, it is a singular event that actually happened, not an artificial construct of the code.
What you want here instead is to respond in two different ways to this user event, this single action. Two different stores will respond to the same action, but in different ways.
So you would have this in the event handler:
MyAppActions.userClicked(itemID);
and that would create an action like this:
userClicked: function(itemID) {
MyDispatcher.dispatch({
type: MyAppActions.types.USER_CLICKED,
id: itemID,
});
},
and that would play out in your stores like:
switch (action.type) {
case MyAppActions.types.USER_CLICKED:
this._handleUserClicked(action.id);
break;
// ...
}
In the two stores, the implementation of _handleUserClicked would do things specific to the particular store.
There's no reason to prefer one over another, Eric -- unless you need them to be done in a specific order. If that's the case, you probably want to have the First Action do its thing then call the Second Action (which you identified in No. 2 above). But if there's no ordering, there's no particular reason to prefer any of the three methods you outlined.
Like Hal stated, it depends on what you're using them for.
The UI Component calls two ActionCreator methods. Each ActionCreator dispatches a message.
I think this is the best solution if you're not specifically sure what you'll use the actions for. If there's any chance the methods could be called individually in other circumstances, it will be easier if you have the UI component call two ActionCreator methods.
The UI Component calls one ActionCreator method which dispatches a message and calls another ActionCreator method.
It's a good point that if you need actions to be done in a certain order, you should have one action that calls another to be sure that the first action completes before the second one begins.
The UI Component calls one ActionCreator method which does not dispatch any message, but calls two other ActionCreator methods which each dispatch their own message.
I think this is probably the least useful because it does the same thing as situation 1 but forceably binds those two actions together. Only use this if you'll always need both actions to be executed.
Should the stores maintain their own state and have the ability to call network and data storage services in doing so ...in which case the actions are just dumb message passers,
-OR-
...should the stores be dumb recipients of immutable data from the actions (and the actions be the ones that fetch/send data between external sources? Store in this instance would act as view-models and would be able to aggregate / filter their data prior to setting their own state base on the immutable data they were fed by the action.
It seems to me that it should be one or the other (rather than a mix of both). If so, why is one preferred / recommended over the other?
I've seen the flux pattern implemented both ways, and after having done both myself (initially going with the former approach), I believe that stores should be dumb recipients of data from the actions, and that asynchronous processing of writes should live in the action creators. (Async reads can be handled differently.) In my experience, this has a few benefits, in order of importance:
Your stores become completely synchronous. This makes your store logic much easier to follow and very easy to test—just instantiate a store with some given state, send it an action, and check to see if the state changed as expected. Furthermore, one of the core concepts in flux is to prevent cascading dispatches and to prevent multiple dispatches at once; this is very difficult to do when your stores do asynchronous processing.
All action dispatches happen from the action creators. If you handle asynchronous operations in your stores and you want to keep your stores' action handlers synchronous (and you should in order to get the flux single-dispatch guarantees), your stores will need to fire additional SUCCESS and FAIL actions in response to asynchronous processing. Putting these dispatches in the action creators instead helps separate the jobs of the action creators and the stores; furthermore, you don't have to go digging through your store logic to figure out where actions are being dispatched from. A typical asynchronous action in this case might look something like this (change the syntax of the dispatch calls based on the flavor of flux you're using):
someActionCreator: function(userId) {
// Dispatch an action now so that stores that want
// to optimistically update their state can do so.
dispatch("SOME_ACTION", {userId: userId});
// This example uses promises, but you can use Node-style
// callbacks or whatever you want for error handling.
SomeDataAccessLayer.doSomething(userId)
.then(function(newData) {
// Stores that optimistically updated may not do anything
// with a "SUCCESS" action, but you might e.g. stop showing
// a loading indicator, etc.
dispatch("SOME_ACTION_SUCCESS", {userId: userId, newData: newData});
}, function(error) {
// Stores can roll back by watching for the error case.
dispatch("SOME_ACTION_FAIL", {userId: userId, error: error});
});
}
Logic that may otherwise be duplicated across various actions should be extracted into a separate module; in this example, that module would be SomeDataAccessLayer, which handles doing the actual Ajax request.
You need less action creators. This is less of a big deal, but nice to have. As mentioned in #2, if your stores have synchronous action dispatch handling (and they should), you'll need to fire extra actions to handle the results of asynchronous operations. Doing the dispatches in the action creators means that a single action creator can dispatch all three action types by handling the result of the asynchronous data access itself.
I tweeted this question to the devs at Facebook and the answer I got from Bill Fisher was:
When responding to a user's interaction with the UI, I would make the async call in the action creator methods.
But when you have a ticker or some other non-human driver, a call from the store works better.
The important thing is to create an action in the error/success callback so data always originates with actions
The stores should do everything, including fetching data, and signalling to components that the store's data has been updated. Why? Because actions can then be lightweight, disposable and replaceable without influencing important behavior. All important behavior and functionality happen in the store. This also prevents duplication of behavior that would otherwise be copied in two very similar but different actions. The stores are your single source of (handling the) truth.
In every Flux implementation I've seen Actions are basically event strings turned into objects, like traditionally you'd have an event named "anchor:clicked" but in Flux it would be defined as AnchorActions.Clicked. They're even so "dumb" that most implementations have separate Dispatcher objects to actually dispatch the events to the stores that are listening.
Personally I like Reflux' implementation of Flux where there are no separate Dispatcher objects and Action objects do the dispatching themselves.
edit: Facebook's Flux actually fetches in "action creators" so they do use smart actions. They do also prepare the payload using the stores:
https://github.com/facebook/flux/blob/19a24975462234ddc583ad740354e115c20b881d/examples/flux-chat/js/actions/ChatMessageActionCreators.js#L27 (line 27 and 28)
The callback on completion would then trigger a new action this time with the fetched data as payload:
https://github.com/facebook/flux/blob/19a24975462234ddc583ad740354e115c20b881d/examples/flux-chat/js/utils/ChatWebAPIUtils.js#L51
So I guess that's the better solution.
I'll provide an argument in favor of "dumb" Actions.
By placing the responsibility for collecting view data in your Actions, you couple your Actions to the data requirements of your views.
In contrast, generic Actions, that declaratively describe the intent of the user, or some state transition in your application, allows any Store that responds to that Action to transform the intent, into state tailored specifically for the views subscribed to it.
This lends itself to more numerous, but smaller, more specialized Stores. I argue for this style because
this gives you more flexibility in how views consume Store data
"smart" Stores, specialized for the views that consume them, will be smaller and less coupled for complex apps, than "smart" Actions, on which potentially many views depend
The purpose of a Store is to provide data to views. The name "Action" suggests to me that its purpose is to describe a change in my Application.
Suppose you have to add a widget to an existing Dashboard view, which shows some fancy new aggregate data your backend team just rolled out.
With "smart" Actions, you might need to change your "refresh-dashboard" Action, to consume the new API. However, "Refreshing the dashboard" in an abstract sense has not changed. The data requirements of your views is what has changed.
With "dumb" Actions, you might add a new Store for the new widget to consume, and set it up so that when it receives the "refresh-dashboard" Action type, it sends a request for the new data, and exposes it to the new widget once it's ready. It makes sense to me that when the view layer needs more or different data, the things that I change are the sources of that data: Stores.
gaeron's flux-react-router-demo has a nice utility variation of the 'correct' approach.
An ActionCreator generates a promise from an external API service, and then passes the promise and three action constants to a dispatchAsync function in a proxy/extended Dispatcher. dispatchAsync will always dispatch the first action e.g. 'GET_EXTERNAL_DATA' and once the promise returns it will dispatch either 'GET_EXTERNAL_DATA_SUCCESS' or 'GET_EXTERNAL_DATA_ERROR'.
If you want one day to have a development environment comparable to what you see in Bret Victor's famous video Inventing on Principle, you should rather use dumb stores that are just a projection of actions/events inside a data structure, without any side effect. It would also help if your stores were actually member of the same global immutable data structure, like in Redux.
More explainations here: https://stackoverflow.com/a/31388262/82609