Problems with architecture of the redux store - reactjs

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.

Related

Chain redux store update

I would like to dispatch an action after a first one has been processed by the reducers.
Here is my use case. My component allows the user to select a list of notes (this list is store in redux). Based on some user actions, a random note can be selected from this list and saved in the store.
In the screenshot you can see buttons. "Select All" and "Unselect All" act on the list of possible note. "Start" pick a note from the list.
The issue I have concern the "reset button". It is supposed to chain "select all" and "start" and I don't know how to do that. I tried a naive:
const reset = function () {
dispatch(selectAll());
dispatch(pickANote());
}
With this example, I am facing what I think is a data race. The second action pick a note from a note updated list.
Digging the internet, I found only cases of action chaining based on API calls with redux thunk. The problem I have is that I don't know how to trigger something when a action is processed (which is obvious with an API call)
So, there is 3 solutions:
I am missing something obvious
I am going where no man has gone before
I am doing something anti-pattern
Any help is welcome.
Alright, I found my answer.
No surprise, I was thinking anti-pattern.
In the redux style guide, there is 2 points that lead me to the solution.
It is strongly recommended to dispatch one action that is processed
by several reducers.
It is strongly recommended to put the logic inside the reducers.
The consequence is that I should dispatch "raw data" and then compute value reducers. Following this path, I am not dependent on the values already in the store for the next updates and so, I do not face any data race.

using window.store to make the redux store global is a good idea or not?

When using redux, after creating store, I think we could make it global by
set it to window.store = store1 for example.
If I could use this, I could freely subscribe or dispatch to the store in any component. My question is why I need to use react-redux?
That way you can only read the data on mounted once. For every changes after that, you need a way to trigger your component to re-render (i.e. update either props or state), thus the need for redux selectors.
I'm seeing a similar need for window.store. There are benefits like being able to say window.store.getState() while debugging, it means you can call action functions that have several dispatches without running them thru mapDispatchToProps and "dispatching" things that aren't action creators. Hard to know if this is a a good idea or a bad one, but it has definitely made a good bit of the code a lot easier to read.

Is it bad practice to do calculations and data tweaking in the saga in react?

I have a saga which runs once every 10 seconds on a POLL action to updated the current state on my GUI.
when a POLL happens I need to make a few calls to walk down the rest interface to get to find the components I care about. There will be a total of 1-5 components, for each of these I need to make a separate rest call for Foo and Bar elements of the components.
Then at some point I need to do some summations, combining the Foo and Bar data together to have the structure expected by my table for listing components, calculating some totals across all components in my dashboard etc. None of the work is cpu intensive, but it adds up to a decent bit of code since I have so many things that need tweaked.
Currently I'm doing all of this in the Saga, but I'm not sure if this is considered bad practice? I feel like reducers are the general 'go to' place for data tweaking, but it feels odd throwing an action with such a large payload, all the responses from every call in a saga, since much of the rest response is data I don't care about. I also like doing all the processing in the saga so I can decide at the end of everything rather to pass an error action to show an error to the user or pass a success action which clears any previous errors, some of the decision for rather I want to clear the action requires more processing of the data.
My only concern is that the generator is getting rather large, with lots of helper methods that feel a little out of place in a saga class to do the processing (their need to be moved to a utils class no matter what I think). The processing isn't too expensive and I am using generators so I don't think the processing will have a noticeable affect on saga's 'threading'. Still, If there is a recommended best practice I want to stick to that. Am I breaking from standard practices doing all of my tweaking of the data in my saga and sending to the reducer a per-formatted object for it to store into the state without any other processing?
This is really a specific case of a common question that is addressed by the Redux FAQ on "where should my business logic live?". Quoting that answer:
Now, the problem is what to put in the action creator and what in the reducer, the choice between fat and thin action objects. If you put all the logic in the action creator, you end up with fat action objects that basically declare the updates to the state. Reducers become pure, dumb, add-this, remove that, update these functions. They will be easy to compose. But not much of your business logic will be there. If you put more logic in the reducer, you end up with nice, thin action objects, most of your data logic in one place, but your reducers are harder to compose since you might need info from other branches. You end up with large reducers or reducers that take additional arguments from higher up in the state.
There's nothing wrong with having logic on the "action creation" side (whether it be in components, thunks, sagas, or middleware) that does a lot of work to prepare and format data, and having the reducer simply store what was included in the action. On the flip side, having more logic on the reducer side can mean that time-travel debugging will re-run more of your actual code, giving you more chances to edit and retry behavior.
Overall, it sounds like what you're doing is perfectly reasonable.

what is this difference between this flux action and this function call?

I could a have a flux action like this:
{type: 'KILL', payload: {target: 'ogre'}}
But I am not seeing what the difference is between having a method on a class People (wrapping the store) like this,
People.kill('ogre')
IF People is the only receiver of the action?
I see that the flux dispatcher gives me two advantages (possibly)
The "kill" method can be broadcast to multiple unknown receivers (good!)
The dispatcher gives me a handy place to log all action traffic (also good!)
These might be good things sure, but is there any other reasons that I am missing?
What I don't see is how putting the actions in the form of JSON objects, suddenly enforces or helps with "1-way" communication flow, which is what I read everywhere is the big advantage of having actions, and of flux.
Looks to me like I am still effectively sending a message back to the store, no matter how I perfume the pig. Sure the action is now going through a couple of layers of indirection (action creator, dispatcher) before it gets to the store, but unless I am missing something the component that sends that action for all practical purposes is updating whatever stores are listening for the kill message.
What I am missing here?
Again I know on Stack Overflow we can't ask too general a question, so I want to keep this very specific. The two snippets of code while having different syntax, appear to be semantically (except for the possibility of broadcasting to multiple stores) exactly the same.
And again if the only reason is that it enables broadcasting and enables a single point of flow for debug purposes, I am fine with that, but would like to know if there is some other thing about flux/the dispatcher I am missing?
The major features of the flux-style architecture are roughly the following:
the store is the single source of truth for application state
only actions can trigger mutation of the store's state
store state should not be mutated directly, i.e. via assigning object values, but by creating new objects via cloning/destructuring instead
Like a diet, using this type of architecture really doesn't work if you slip and go back to the old ways intermittently.
Returning to your example. The benefit for using the action here is not broadcasting or logging aspects, but simply the fact that the People class should only be able to either consume data from a store and express its wishes to mutate the state of said store with actions. Imagine for example that Elves want to sing to the the ogre and thus are interested in knowing the said ogre is still alive. At the same time the People want to be polite and do not wish to kill the ogre while it is being serenaded. The benefits of the flux-style architecture are clear:
class People {
kill(creature) {
if (creatureStore.getSerenadedCreature() !== creature)
store.dispatch({ type: 'KILL', payload: { target: creature } })
return `The ${creature} is being serenaded by those damn elves, let's wait until they've finished.`
}
}
class Elves {
singTo(creature) {
if (!creatureStore.getCreatures().includes(creature))
return store.dispatch({ type: 'SING_TO', payload: { target: creature } })
return `Oh no, the ${creature} has been killed... I guess there will be no serenading tonight..`
}
}
If the class People were to wrap the store, you'd need the Elves class to wrap the same store as well, creating two places where the same state would be mutated in one way or the other. Now imagine if there were 10 other classes that need access to that store and want to change it: adding those new features is becoming a pain because all those classes are now at the mercy of the other classes mutating the state from underneath them, forcing you to handle tons of edge cases not possibly even related to the business logic of those classes.
With the flux style architecture, all those classes will only consume data from the creatureStore and dispatch actions based on that state. The store handles reconciling the different actions with the state so that all of its subscribers have the right data at the right times.
The benefits of this pattern may not be evident when you only have a couple of stores that are consumed by one or two entities each. When you have tens (or hundreds) of stores with tens (or hundreds) of components consuming data from several stores each, this architecture saves you time and money by making it easier to develop new features without breaking existing ones.
Hope this wall-o-text helped to clarify!
What I don't see is how putting the actions in the form of JSON objects, suddenly enforces or helps with "1-way" communication flow, which is what I read everywhere is the big advantage of having actions, and of flux.
Looks to me like I am still effectively sending a message back to the store, no matter how I perfume the pig. Sure the action is now going through a couple of layers of indirection (action creator, dispatcher) before it gets to the store, but unless I am missing something the component that sends that action for all practical purposes is updating whatever stores are listening for the kill message.
What I am missing here?
Facebook Flux took the idea from the event driven GUI systems.
In there even if you move your mouse you get messages. This was called message loop then, and now we have actions dispatching.
Also, we have lists of subscribers inside stores.
And it is really the same principle in Redux where you have one store, while in Flux you may have multiple stores.
Now little mathematics. Having 2 components A and B you need to have just a few possible update chains A updates B and B update A, or self-update (non including in here the updates from outside of the app). This is the possible case.
With just three components we have much more possible chains.
And with even more components it gets complicated. So to suppress the exponential complexity of possible components interaction we have this Flux pattern which in nothing more than IDispatch, IObservable if you worked with these interfaces from some other programming languages. One would be for spitting the actions, and the other for entering the listener's chain that exists inside the store.
With this pattern, your React code will be organized in a different way than common React approach. You will not have to use React.Component state anymore. Instead, you will use the Store(s) that will hold the application state.
Your component can only show the desire to mutate the application state by dispatching the action. For instance: onClick may dispatch the action to increment the counter. The actions are objects with the property type: that is usually a string, and usually in upper case, but the action object may have many other props such as ID, value,...
Since the components are responsible for rendering based on the application state we need somehow to deliver them the application state. It may be via the props = store.getState() or we may use the context. But also check this.
Finally, it is even not forbidden that component uses the internal state (this.state) in case this has no impact on the application. You should recognize these cases.

Why do we need dispatcher in Flux?

This is not a React specific question. I'm thinking of implementing Flux in Aurelia/Angularjs.
While reading up on flux, I'm not convinced of the need of the dispatcher step. Why can't a component call the store directly to update and retrieve data? Is there anything wrong with that approach?
For example: If I have a CarStore that can create new cars, update cars and get a list of cars(just a thin layer on the CRUD api), I should be able to retrieve/update the list by directly calling the store from the car-grid component. Since the store is a singleton, whenever the list updates, car-grid should automatically get the new items. What is the benefit of using a dispatcher in this scenario?
I've created several large apps using React-native with Redux as the store / view state updater.
The dispatch action is synchronous regardless. There's a big disadvantage to using dispatchers, you lose the function signature. (Debugging, auto-catching type-errors, refactoring lost, multiple declarations of the same function, list goes on)
Never had to use a dispatcher and its caused no issues. Within the actions we simply call getState().dispatch. The store is a singleton anyhow, it's heavily recommended you don't have multiple stores. (Why would you do that...)
You can see here why are dispatchers important (check out the section Why We Need a Dispatcher). The way I see it, the idea is basically being able to access to various stores in a synchronous way (one callback finishes before another one is called). You can make this thanks to the waitFor method, which allows you to wait for a store to finish processing an action (or more tan one). There is a good example in the docs. For example, your application may grow and instead of having just that CarStore you have another Store whose updates depend on the CarStore updates.
If you will only ever have one store, then a dispatcher is redundant in my opinion. If you have multiple stores however, then a dispatcher is important so that actions don't need to know about each of these stores.
Please note that I am not saying that you should ditch the dispatcher if you only have one store. It's still a good pattern as it gives you the option of supporting multiple stores if you ever need to in the future.

Resources