I am currently dealing with a very large table of data. Some actions the user can take are quite complex - complex enough that I might end up dispatching a hundred actual actions to Redux, many of which will depend on the state being updated by previous actions, and causing a hundred state changes... which will result in the page seeming to lock up as numerous things in a very large table are rendered a hundred times, even though none of these updates will be individually meaningful to the user (or actively confusing)
Is there a way to delay Redux/React from seeing these changes - to say "okay, don't bother pestering React about this stuff, don't recalculate any props, don't do anything but throw this stuff through the reducers until it's done and I tell you it's done, and then return to normal behaviour" ?
I know I could set some React state property and then have a shouldUpdateComponent in each of my many components, but I was hoping there was a solution that involved less duplicate code scattered across dozens of files and perhaps even a bit more efficiency of avoiding calling the same exact function dozens of times per update.
Any suggestions?
Dan Abramov himself wrote on twitter an example of how to do this using batched actions and a higher order reducer.
https://twitter.com/dan_abramov/status/656074974533459968?lang=en
The gist of the idea is to wrap the actions you want to batch in another action, and define a higher order reducer (a reducer that returns another reducer, eg. redux-undo) that will apply all these actions when it handles the batched action update.
Related
I have run into a performance issue with react redux, and I have been reading a bit about, and per what I ended up with, it "seems" like I am doing it all "correct".
I have a situation where I have a production line tracking system, and for each "project" there is 12 steps that it goes through.
I have about 60-100 projects going on every week, split into days, easily visible on 1 view.
Now the problem lies in the fact that, each of those 12 steps, are individual components that I connected up using the React Redux Connect function, which basically maps the flat store state of all the different steps, and searched out that exact step from the store, which contains data about when it was done, its status etc, and then it throws that into it as a prop, and uses it to render.
Now, everytime I create an update into the store of the list of steps, it obviouslly rerenders those aprox 1000 components, and checks whether or not they need to rerender, which only 1 of them then does, the one that I clicked on, lets say.
However, the whole computing part of looping through 1000 mapToState functions takes time, and slows down the app and makes it irresponsive.
Is there a smarter way to go about connecting up the components to the store.
As a note, I have thought about this long before writing this, and I have also tried to map up only each project (each set of 12 steps), and have them then render pure components based on that as a parent, sending down each individual step to the child component with the data, however, I don't get any better result.
Thanks in advance for anyone who can help with some guidance or pushing me in the right direction.
Vincent Rye
I'm currently in this situation and am also looking for a definitive answer, but I'll share what I've come up with so far:
For a web app to hit a target of 60fps you have a per-frame budget of 16.67ms per frame.
If you have 1,000 connected components there's some amount of redux bookkeeping (like running mapStateToProps) that will happen on every store update for every component, and to stay within a frame budget of 16.67ms you'll need that bookkeeping to happen within 0.017ms (or 17,000ns) on average.
From experience, that has been hard to achieve for us.
Currently I have a large list of data (500 Rows) that at times many records can be updated a second. I'm using firebase's Real time Database. I am using React and Redux and basically whenever a record is changed, I fire a dispatch event to update the state in my app. When there are many records being updated it slows down and almost crashes the browser.
I've narrowed down my performance issues to it trying to dispatch 200+ actions at once. But since it is websockets/firebase I have no way of getting these updates in groups.
I am wondering if there is a library to use that will queue the dispatch requests and update the state one at a time, in order. Instead of trying to do it all at once.
Are these issues by any chance occurring in development with Redux dev tools also running?
Redux is fairly optimised to handle large data sets (particularly if you normalise your data structure). However, if you are dispatching a large number of actions and also have a large amount of data in your Redux store, using Redux dev tools can give a somewhat false impression of poor performance.
In a production build of your application there would only ever be one instance of your Redux state at a particular moment. Hence the first of the three Redux principles; single source of truth.
The difference whilst using Redux-dev tools in development however is that the dev tools keep a history of your actions and the state for each action dispatch you trigger. This subsequently can lead to large amounts of that data filling up your browser’s memory and thus giving the perception of poor performance.
You can also take a look at the Redux documentation on performance which has several further suggestions for how you can optimise your application.
If you would also like to show us how your data is structured in your reducer, or how you are handling your action dispatches, perhaps we can make further suggestions to improve your performance.
I have been using vanilla React for a while, and have now decided to take a closer look at Redux for a new project I am doing.
At first I got the impression that all user activity should result in actions, with one of the main reasons being that you would be able to reconstruct any application state by just playing back the appropriate actions.
The problem with this, however, is that you put a lot of stuff in the store that in reality does not feel like application state. Stuff like "If I focus on this input, the label turns green" does not seem like state fitted for being represented in the application state of an application that is potentially composed by hundreds of components. These things make total sense with the typical todo-tutorial, but it can be difficult to see how it will turn out in a more complex scenario.
Then I read some more, and found that the general opinion, backed by creator Dan Abramov, is that you should usually combine local component state with the application state (store). "Whatever seems least awkward" seemed to be the rule of thumb for where to store state.
On one hand this makes total sense: The things that are really application state, and are relevant for multiple components should be in the store, while the strictly presentational details that only concerns one single component should be handled using normal react state. On the other hand this approach confuses me a bit, because of what I wrote in the beginning: Isn't a big part of the point with redux that you avoid having the state distributed among the components, and that you are able to recreate state by just storing the actions?
I hope someone can shed some light on this concern, because it has been bothering me, and it is something I think I should get a solid opinion about before trying to build something complex with redux.
What state you put where is entirely up to you. Sometimes it may make sense to put everything in Redux, sometimes it may make sense to keep stuff in a component. I recently saw some good rules-of-thumb:
Do other parts of the application care about that data?
Do you need to be able to derive further data from that data?
Is the same data being used to drive multiple components/features?
Is there value to you, to being able to restore the state to a given point in time (ie: time travel / debugging)?
Do you want to cache the data, ie: reload it from state if it's already there instead of requesting it again?
(Credit to https://www.reddit.com/r/reactjs/comments/4w04to/when_using_redux_should_all_asynchronous_actions/d63u4o8 for that list.)
Also see the Redux FAQ on this topic: http://redux.js.org/docs/FAQ.html#organizing-state-only-redux-state .
I have a react/redux application which has become large enough to need some performance optimizations.
There are approx ~100 unique components which are updated via websocket events. When many events occur (say ~5/second) the browser starts to slow down significantly.
Most of the state is kept in a redux store as Immutable.js objects. The entire store is converted to a plain JS object and passed down as props through the component tree.
The problem is when one field updates, the entire tree updates and I believe this is where there is most room for improvement.
My question:
If the entire store is passed through all components, is there an intelligent way to prevent components updating, or do I need a custom shouldComponentUpdate method for each component, based on which props it (and its children) actually use?
You really don't want to do things that way. First, as I understand it, Immutable's toJS() is fairly expensive. If you're doing that for the entire state every time, that's not going to help.
Second, calling toJS() right away wastes almost the entire benefit of using Immutable.js types in the first place. You really would want to keep your data in Immutable-wrapped form down until your render functions, so that you get the benefit of the fast reference checks in shouldComponentUpdate.
Third, doing things entirely top-down generally causes a lot of unnecessary re-rendering. You can get around that if you stick shouldComponentUpdate on just about everything in your component tree, but that seems excessive.
The recommended pattern for Redux is to use connect() on multiple components, at various levels in your component tree, as appropriate. That will simplify the amount of work being done, on several levels.
You might want to read through some of the articles I've gathered on React and Redux Performance. In particular, the recent slideshow on "High Performance Redux" is excellent.
update:
I had a good debate with another Redux user a couple days before this question was asked, over in Reactiflux's #redux channel, on top-down vs multiple connections. I've copied that discussion and pasted it in a gist: top-down single connect vs multiple lower connects.
Also, yesterday there was an article posted that conveniently covers exactly this topic of overuse of Immutable.js's toJS() function: https://medium.com/#AlexFaunt/immutablejs-worth-the-price-66391b8742d4. Very well-written article.
I'm creating an app with Redux and am scratching my head as to why it is best to place actions and reducers in separate files. At least, that's the impression I'm getting from all the examples.
Each action, or action creator, appears to map to a single function that is called by a reducer (inside a switch statement). Wouldn't it be logical to keep these together in the same file? It also makes using the same constant for the action type and switch case easier, as it doesn't have to be exported/imported between files.
From Redux creator Dan Abramov:
Many reducers may handle one action. One reducer may handle many
actions. Putting them together negates many benefits of how Flux and
Redux application scale. This leads to code bloat and unnecessary
coupling. You lose the flexibility of reacting to the same action from
different places, and your action creators start to act like
“setters”, coupled to a specific state shape, thus coupling the
components to it as well.
From the Redux docs:
We suggest you write independent small reducer functions that are each
responsible for updates to a specific slice of state. We call this
pattern “reducer composition”. A given action could be handled by all,
some, or none of them. This keep components decoupled from the actual
data changes, as one action may affect different parts of the state
tree, and there is no need for the component to be aware of this.
See this conversation on twitter and this issue on github for more information.
Keeping Actions and Reducers in separate files helps keep the code modular.
It can be easier to find bugs, extend the code, and in general work on the smallest piece possible.
Example:
Saving API error messages to the Redux store can be helpful.
If I forgot to update the store with the incoming error on one of the Reducers, that could be tough to find across multiple files.
If I'm looking at multiple Reducers in the same file, it'll be easier to see that one of them is missing the error: action.payload line.