Does Redux have a nicer way to handle a very large state object? - redux

We're planning an Electron app, and we're considering Redux. The app is going to have a huge state, data potentially being read from dozens or hundreds of files. While doing some research to understand Redux, I found that the reducer method must never alter the state, and must create a new state with any changes. This is going to be a problem if the state of the app is very large, since now we need to deeply copy everything in the state (it's going to be a bunch of nested objects), and we're going to take up double the memory that was being used to hold the state once, then the old state will be deleted. This doesn't seem ideal at all.
Is there a better way to handle this in situation in Redux?

You shouldn't deeply copy. In fact, I'd say deep-copying is counter-intuitive to the redux-way.
You'll be copying by reference most of the time, which is very fast.
If you're worried about your state tree being too large, I recommend redux-ignore, to break things down.
I'm currently running a redux app that has over 200 reducers. I've yet to detect a bottleneck due to redux, even on cheap android mobile devices.

Related

What's the actual downside of storing functions / components on Redux?

I would like to store a function / component inside the Redux state to pass it to another part of the application.
I've read that this is not recommended, but what exactly will happen?
Will it affect the performance of other data stored on Redux to the point it becomes visibly slow to the user?
Will it cause components that depend on this component or any data stored on Redux to continuously re-render causing the app to slow to a crawl?
Will Redux just break randomly all the time?
What are the actual, practical downsides to doing this, putting aside the intentions behind the creation of the library?
Do not put functions or components (non-serializable value) in redux state or actions
Avoid putting non-serializable this can break the following things:
debugging
server side rendering
state persistence
and more, this can create performance issue
This is described more in depth here in the official documentation
I've decided to just store the component I needed on Redux and haven't seen any downsides, which led me to believe there is no real issue in doing this, as long as you don't care about serialization.

Redux - keeping related reducers in sync

I'm building an Angular 1.5 app right now that I am incrementally adding Redux to. I'm coming across a problem that I'm having a hard time finding a good solution for. My application mostly deals with widgets that display data and manage the configurations that define what data is displayed in those widgets. As I add more state to Redux, the widgets reducer is getting enormous. I have broken it up into a few smaller reducers but now I'm wondering about the maintainability of a setup like this.
Essentially I worry that in the future it will be far too easy to modify one reducer or add a new action that operates on widget data and then forget to adjust all of the other reducers to account for this new aspect of the system. Or that the various ways that widget state can change via the reducers will get so complicated that it will be prohibitively difficult to make sure that I have properly adjusted all of the reducers necessary.
A lot of these reducers essentially just need to react when a widget is removed/moved/modified/whatever. I wish there was a simple catch-all way to do that in Redux like a deep watch in vanilla Angular(I know deep watchers should be avoided generally but just as an example). As I convert more of my app to use Redux, these reducers will just get more and more complex. It seems like it's a losing game. Is there some different way of approaching this problem that would be more appropriate for this problem space? Or should I just accept that some reducers are going to be enormous and that is how it has to be? Thanks for any input!
The solution to my specific problem is mostly to keep all state related to a given widget in one object so that I don't end up with redundant data management requirements. I split both state and reducers up and that caused the same logic for managing data cleanup and maintenance to be spread across different reducers. If I just split reducers up by implementing higher order reducers and keep the state in one place for one concept then this problem goes away.

Shouldn't a Redux app with immutable data run out of memory after a while?

I come from a background in embedded systems where you're really careful about memory management. With Redux especially its concept of immutability.
So let's say I'm modifying a member of an array. I have to create a new array that links to all original members plus the modified item.
I understand why using Immutability improves the speed but my question is since we essentially never remove the old copies of the objects and create new ones, Redux still keeps a reference to the old objects because of time traveling features.
Most machines these days have quite a lot of memory, but shouldn't at least in theory the Redux app crash because the tab/process runs out of memory? After a long use maybe?
No. First, Redux itself doesn't keep around old data - that's something that the Redux DevTools addon does. Second, I believe the DevTools addon has limits on how many actions it will track. Third, Javascript is a garbage-collected language, so items that are no longer referenced will be cleaned up. (Hand-waving a bit there, but that generally covers things.)
Immutable.js leverages the idea of Structural Sharing while creating new copies of collections. It implements persistent data structures and internally uses concepts like tries to implement structural sharing. So, if you created a list with 10 items, adding a new item to it will not create a new list.
Persistent data structures provide the benefits of immutability while
maintaining high performance reads and writes and present a familiar
API.
Immutable.js data structures are highly efficient on modern JavaScript VMs by
using structural sharing via hash maps tries and vector tries as
popularized by Clojure and Scala, minimizing the need to copy or cache
data.
I suggest you watch this awesome talk by Lee Bryon, Immutable.js creator

Redux: Syncing backend DB with frontend app state tree

From my experience, keeping backend DB and the frontend state tree in sync becomes a non-trivial task as the app grows more complicated.
For example, when you create a new Post in a blog, you have to create an object in the DB as well as attach a post object in your state tree (ex. inside posts reducer). It gets more complicated if the state tree is nested. If you update a comment that belongs to a post, you have to find the right post in the state tree, and find the right comment and update.
I understand why having an App State Tree is beneficial but this syncing causes too much overhead for me to truly appreciate Redux.
Q. Is there a way to do this syncing more easily?
Meteor is specifically designed to solve the problem you're mentioning.
Redux is only to manage state on the client. More precisely, its job is to hold the state needed for the ui itself.
It's often used with React where it functions as a smart place to stash anything and everything needed to render the ui. This often includes a complicated state and may include a lot of app data. It may then start to look more like a database, but databases have a number of properties that Redux lacks. Persistence comes to mind...
Meteor is a framework and Redux is not. As such, Meteor comes with an enormous amount of buy-in where Meteor decides on how to deal with a large number of issues in your app. Redux on the other hand is very permissive. It doesn't decide on what your state looks like, or how you talk to your backend, or how you render your ui.
So inasmuch as Redux allows you the freedom to decide for yourself how to deal with these issues, it also leaves you with the responsibility to do so. Redux is super tiny and you should only expect rock solid state management, and nothing more.
How much of your global app state you move to the client is entirely up to you, and how you connect it to your backend, and if this backend runs node.js+Mongo or php+mysql or lisp+text files is entirely up to you. The same can not be said when using Meteor.
With great power comes great responsibility.
I have the same question and I'm sure there's a tried-and-true correct response to this. However, I brainstormed two possible solutions:
1) add the post to the app state 'manually', then the next time a GET is requested, reconcile the state and the response (your strategy). This is a lot easier if your client state is normalized
2) do a GET immediately after the POST status is 200, and deal with the latency with an activity indicator.
The accepted answer to me , is not a fundamental explanation.

Redux performance in a large scale JS app

I recently started studying redux, after few hours i got the question in my mind about performance of redux in a large scale web application.
my question is since redux maintains the previous states of the store over time, let's say the application is big enough and having ample amount of state changes over the time, doesn't it reduce the performance of the app since of the increasing memory consumption over time to maintain all the previous states?
FYI : i'm thinking based on java background of garbage collection and releasing the unused memory after some time.
Assuming you use immutable data structures like the ones provided by immutable.js, there is no extra cost to remembering the previous states when adding or updating an existing data structure other than keeping track of references. This is one of the big advantages of using immutable data structures. Of course, when a state change consists of replacing the complete state with something else, these advantages are mitigated.
That said, you don't have to keep track of the previous states, it's just much easier and more effective to do it with immutable data structures.
Also, Redux doesn't remember previous states by default, this is only used in the redux devtools which provides the "time travel" functionality you seem to aim at. This is very handy during development.

Resources