Using redux with a local database - reactjs

I have an offline React web app where all data is stored locally in indexedDB. There is no server other than the file hosting for static assets. I am getting to the point where I am starting to look into using redux now but I am trying to understand the tradeoffs between moving more data into the store and continuing to rely on the DB. What's the idiomatic way of using a local db with redux?
Currently my app is composed of several container components that each fetch data from the db in componentWillMount. One option for integrating redux is to keep this mostly the same, with the only difference being the state is kept in the store and data is fetched using actions and thunks.
Alternately, I have seen lots of example code that loads all the data into the store at launch. This makes the whole app more deterministic, easier to test and reproduce. Switching between the main components would happen instantly (at the expense of initial app load). But I lose the benefits the DB provides like indexes and nice queries.
It seems like it would be unreasonable load literally the whole db into the store, at least in my case, that would be about 10MB of data, maybe more. So I will always have at least some components which will need to continue fetching their data on mount. But there's a subset of data which is central to the app and can be argued that table should be loaded in its entirety (this would be about 5,000 to 10,000 objects, probably).
What's the idiomatic way to work with local storage and redux? I get the sense that async fetches in componentWillMount is not idiomatic if it can be avoided. Even in instances where the state is small enough that it can be fully loaded into the store, is it worth giving up the benefits of a nice efficient query interface?
Edit: I should mention: I am using Dexie, which is a really, really wonderful library for working with indexedDB. It's fast, has a nice query interface, handles migrations etc... I'd really like to continue using Dexie unless there's a really strong reason to do otherwise.
For reference, here's a discussion on this topic on Dexie's github. The general take away form that is "it depends". Not quite the answer I was looking for, so I am hoping to get more insight if possible.

Answering this myself with what I've discovered so far. If I better answer comes along I'll be happy to mark it accepted.
TL;DR: It really does depend. The idiomatic way to do things is indeed to put as much in the state as long as makes sense. However, it is not un-idiomatic to asynchronously fetch data from elsewhere when it makes sense. Many applications would simply be impractical otherwise.
Dan Abramov's egghead tutorial (even titled "Building React Applications with Idiomatic Redux") goes with the approach of having all state in the store and persisting it a s one giant blob (or the relevant slice) periodically.
This has the advantage that you use the redux store as usual and persistence is essentially transparent. If your data is small enough where this isn't a problem this is great.
As #seanyesmunt noted, there is redux-persist, which basically does a more sophisticated version of this.
Of course, shortly after that he then rewrites the tutorial to fetch data from an API. At this point you can just pretend that API is IndexedDB instead, it's really no different. You lose some benefits of redux by not having completely deterministic state as a whole, but in many cases you have no choice.
I ended up doing essentially the same thing as Dexie's Redux sample code. Basically, using thunks to async write to the DB on certain actions.

EDIT 2020-12-18: I recommend using dexie-react-hooks and the useLiveQuery() hook. It's an amazing experience to work with takes away all complexity around this. See also this blog post about it.
My old answer was:
This question is of large interest to me as well as I have been elaborating with react and dexie for the last project I've been in. I am personally examining how graphql could address this scenario, but I am still learning. I hope to provide an example of a graphql/dexie. Of what I understand, graphql would act as the service layer and its "schema" (backend store) would use the dexie queries required to produce the more flat an simplistic graphql data requirements. I will be looking at some ready-to-use grapql sample from Apollo or Facebook to get started and I believe it will be simple to use.
I generally don't think it scales to read entire db into memory. And I believe application startup is crucial to end users so I really hope to find a perfect architecture for this. And currently my hope goes to Graphql.

Related

Statecharts for Redux

Current State Management Stack: React, RTK/Redux, and Redux-Saga
Here's the high level issue. We have a complex flow and we don't have QA Engineering resources to be able to write the integration tests needed for this. This leads to the following issues:
A lot of context needed to change something in this flow(without introducing bugs)
Having to manually test a lot of different paths in the flow to try and make sure nothing was broken
A huge lack of efficiency
Even with dedicated QA effort, bugs still slip through to production with how many paths there are
I've been looking at xstate and really love the ability to generate statecharts(less context needed, non-technical stakeholder understanding, & seems like it would result in better efficiency moving forward). For state management, we currently use Redux across the platform(changing this would be incredibly out of scope). This leads me to my questions:
Does anyone know of a (well supported)npm package where I can integrate Redux with statecharts?
If not, what are the pros/cons of implementing both xstate and Redux? Xstate would only be for this flow and would need to pull some data from Redux. While Redux state is available to xstate, I'm assuming I wouldn't need to write it in a way that Redux is dependent on xstate.
I'm not super familiar with xstate but I don't want to dive too deep if this ends up being a waste of time/terrible idea.
ALSO - for context, this is a very large repo & the solution needs to be maintainable, readable, and most importantly - scalable
ALSO 2 - The main goal of this is the auto-generated statecharts. We have many hands in this flow and keeping documentation up to date manually is not feasible
You can always use statecharts as Redux reducer functions! In fact, one of the XState devs put together an example repo demonstrating exactly how to do that (as well as using XState services in a Redux middleware for side effects):
https://github.com/mattpocock/redux-xstate-poc

What are the true cons of Redux?

I know that Redux is a just option.
While thinking about whether to use Redux or not, I was looking for articles about cons and pros, but there were few recent articles. Old articles have content that I couldn't agree with.
The articles say that boilerplate code and performance are cons of Redux. but, Is it true even now?
Encapsulation
In redux structure, I could access any data(No encapsulation). but, I didn't. It depends on the developer's capabilities and I can care about encapsulation as much as I want.
Cohesion
When I used redux, My code had more cohesion. Data mutation logic is placed in the slice for every feature.
Boilerplate code
I indeed have to make code as the redux way in the Redux structure.
I had to write a little more code in Redux structure, but it was a little bit. Rather, more parts can be reused when using Redux.
When we make a controller in the back-end, we make code in a framework-dependent way. There is almost no one who makes the controller from very low levels because of the flexible design.
Performance
I have made views for some complex use-cases using react-redux. but, I could find meaningful performance down. I think it is also meaningless that there is a performance down due to hundreds of KB of Redux packages.
So my question is...
The articles about Redux cons I read were written 2 years ago. Using the Redux toolkit is a standard way now. Boilerplate code still is a con of Redux?
If the performance down is a con of Redux, Could you tell me specific examples? (What kind of project has performance problems when using redux, or the cases that don't use Redux because of performance.)
What is the biggest con of using Redux today? (Except that it's hard)
Any other thoughts or opinions, please let me know.
While thinking about whether to use Redux or not, I was looking for articles about cons and pros, but there were few recent articles
Different patterns and architectures don't have pros and cons in isolation, they only have pros-and-cons in comparison to some other architecture or pattern. So far you've only written about Redux - you need to compare it to something first.
The articles say that boilerplate code and performance are cons of Redux. but, Is it true even now?
Accusations of needing boilerplate code is not a criticism of Redux I'm familiar with. On the contrary, Redux actually reduces boilerplate compared to the older Flux pattern.
Encapsulation: In redux structure, I could access any data (No encapsulation). but, I didn't. It depends on the developer's capabilities and I can care about encapsulation as much as I want.
Blame JavaScript, not Redux. In JavaScript all objects are (generally) visible for the world to see: which I consider a strength because it makes scripts customizable and hackable, whereas trying to customize a third-party Java or .NET library (where object encapsulation is the norm) is very difficult if not impossible.
Being able to access all data in the state store is by-design. In Redux (and React) your state-store is meant to be a normalized representation of your application's data, so it makes sense for it to be entirely accessible. It doesn't make sense to arbitrarily restrict what data a component can read (it's not like you're running untrusted code).
Remember that state in Redux and React is immutable (i.e. you cannot edit the data in-place), so exposing everything doesn't introduce any risks because a misbehaving component cannot edit state in-place.
To be fair, you need to use Object.freeze to make the data truly immutable, which I imagine most people forget to do...
Encapsulation, as a property of a system's design, can be a good thing - and it can be a bad thing. Encapsulation generally makes sense when you need to hide internal implementation details that are orthogonal (or entirely unrelated) to the data that is being modelled, such as a Array<T>'s internal buffer pointers or a Map<K,V>'s hashtable buckets. But consider that in JavaScript those types (Array, Map, etc) are built-ins and you can use them to model your immutable state: you can't see into Map's buckets or Array's internal pointers, so you actually never stopped using encapsulated objects.
Cohesion: When I used redux, My code had more cohesion. Data mutation logic is placed in the slice for every feature.
I think you misunderstand what "cohesion" actually means in this context. I don't see how the fundamental design of Redux and its state-reducers relate to any concept of cohesion.
Boilerplate code: I indeed have to make code as the redux way in the Redux structure. I had to write a little more code in Redux structure, but it was a little bit. Rather, more parts can be reused when using Redux. When we make a controller in the back-end, we make code in a framework-dependent way. There is almost no one who makes the controller from very low levels because of the flexible design.
I cannot fully comprehend the above paragraph: the last couple of sentences have nothing to do with the rest of the text.
That said, I appreciate that Redux and React both require a fair bit of repetitive declarations for reducers, actions, and action-creators, but I wouldn't describe it as "Boilerplate" code because the information-theoretic content of those (repetitive) declarations is still very high.
Performance: I have made views for some complex use-cases using react-redux. but, I could find meaningful performance down. I think it is also meaningless that there is a performance down due to hundreds of KB of Redux packages.
The runtime performance of Redux is unrelated to the size of Redux libraries. You are conflating completely separate issues.
That said, I don't know where you're getting the idea that Redux requires you to have "hundreds of KB" of JS files because my last Redux project had a single redux.js file sized at 25KB, which was minified to redux.min.js which was only 6KB in size.
I assume you're referring to the #reduxjs/toolkit library (which has 210KB of source files, but the runtime redux-toolkit.umd.min.js is only 33KB.
Now there is something to be said about the performance cost of the Virtual DOM features in ReactJS, but ReactJS is not Redux. You're free to manipulate the DOM however you like when you use Redux directly - so this point is moot.
There is also a discussion to be had about the performance implications of having to clone immutable state compared to mutating state in-place, however immutable data has inherent qualities which mean you can safely clone-by-reference rather than cloning-by-value. And because Redux uses a directed (ideally acyclic) object-tree graph to represent immutable state it takes advantage of the fact that references to unchanged child objects can be safely passed to constructors of new immutable state (so, for example, if you have megabytes of data evenly-distributed throughout your normalized state graph, and your action and reducer only changes a single deeply-nested object property, then the only about log n data will be reallocated and copied, instead of the entire graph.
The articles about Redux cons I read were written 2 years ago. Using the Redux toolkit is a standard way now. Boilerplate code still is a con of Redux?
What boilerplate are you even talking about?
If the performance down is a con of Redux, Could you tell me specific examples? (What kind of project has performance problems when using redux, or the cases that don't use Redux because of performance.)
Think about it this way: JavaScript is far, far from being the fastest or most efficient programming language (e.g. the V8 JS engine will consume tens of megabytes of RAM just to run a simple "Hello, World" example script) - given that, I wouldn't worry too much about general performance in JS (...at least nothing beyond ensuring that any algorithms you implement in JS run in O(n log n) time or better).
What is the biggest con of using Redux today? (Except that it's hard)
I'd say the biggest disadvantage is having to put up with questions like that.
Any other thoughts or opinions, please let me know.
People use Redux because they want to ensure the data-flow through their JS code is consistent, predictable, and straightforward to reason about compared to ad-hoc JS scripts that don't conform to any overall general architecture or programming patterns. If you don't need those benefits then you might just be better-off doing writing ad-hoc JS.

Is it worth using Redux with a Meteor / React app?

I've used Meteor a fair bit and love it, the publish/subscribe model, the way the whole framework is thought out, the ease of writing the server-side code...and I've used React with Meteor, and that's also cool.
However I've recently done a non-Meteor project in React/Redux and there's a lot to love about Redux. It's more effort to set up but the single point Store and all the associated tools/systems are very nice.
My web app will do a lot of database interaction and needs optimistic UI.
So I'm wondering whether to use Meteor/React/Redux for my next project, especially as there are some limitations in MiniMongo (e.g. no support for arrays). However I'm not finding a lot of relevant tutorials on how to hook them together, for example this one is nearly 3 years old now. This makes me doubt whether many people are using this setup, and whether I'll be able to get it working easily: I know from past experience that I need step by step tutorials to get past the initial hurdles with a new setup, then after that I can work things out for myself.
I'll use Meteor/Redux next for sure. I know them, I like them. The question is whether adding Redux is worth the overhead? I hope this is a suitable question for StackOverflow, if not I will try posting it elsewhere.
I'd like to hear reasons to use or not use Redux with Meteor/React, and any recommendations for tutorials. Thank you.
I think Redux is applicable in the non-meteor world, although there are alternatives now with graphql local state or the use of the React context api (which, thanks to React Hooks, is no longer deprecated)
Anyway, back to the story...
I have two separate Meteor apps, one that uses Redux, and the other that doesn't.
Redux works well with Meteor, it does the async thing quite well, but it adds a whole lot of complexity for arguable benefit. In a non-meteor app where you are doing much more in the way of orchestrating asynchronous API calls, then it makes total sense, because you can effectively decouple the data handling from the UI.
But in a typical Meteor app, use of publications and subscriptions means that the data flows naturally anyway. A UI button requests a back end action. The Meteor method does the work, and updates the database, and that data is updated in the UI automatically.
Let's take a scenario that I implemented recently. Members of my app need a Working With Children Check. They are issued a number, and when we are processing membershio renewals, we need to check that the number is still valid. This is initiated by a button on the UI, which calls a Meteor method, which in turn does an API call. The method simply updates the results of the check (even if it fails) into the member's database record. A return value from the Meteor call allows us to do a toast notificaton for the user, and pub/sub looks after updating the new status in the UI.
This could also be done with Redux, but pretty much all of the above code needs to be done anyway.
My preference is away from Redux, as there are alternatives, and it feels like it is a level of engineering that takes you away from writing your app.

Redux and ALL the application state

in the Redux documentation is written:
In Redux, all the application state is stored as a single object.
And that starts my problem.
I'm writing an application that will manage few entities with many data in a SPA (React + Redux) and something is concerning me in to using Redux and get some kind of lag because the quantity of data that I'll need to manage.
I don't believe that transferring all the application state over Redux would be nice, because in some way, it may consume a lot of memory, but I may be wrong.
Redux looks like (to me) so simple and so confuse at the same time and I don't if I should or shouldn't use this, but, the application will grown a lot and I have sure that it will help me to maintain the project organized as well.
Another thing that scared me is about rendering DOM element when an updated state occur. It's different from using setState() on React and as we can see in the Redux videos from Dan Abramov, he is using a forceUpdate wich isn't recommended in the React docs.
Is it possible to manage the entities in different stores but put them together just when it is necessary?
Will it consume a lot of memory if storing all the application state in a single store object?
What's the best way to render React components using Redux?
You've definitely got several different questions there, and you are over-thinking things :)
First, caching data on the client-side is no different in Redux than with any other Javascript framework. In fact, caching data with Redux will likely take up less memory than it would with something like Backbone, because a Redux app will store plain JS objects and arrays rather than wrapping the data in model class instances. There's also no difference size-wise between splitting that data between multiple stores, and combining it all into a single state tree in one store.
Now, how much data you cache is up to you, but realistically you could easily load tens of thousands of records into a client app over time without having issues.
Second, don't confuse the small examples that Dan shows in those videos with how the React-Redux library really works. Dan was trying to illustrate some basic ideas, not show production-grade code. If it helps, he actually wrote a miniature version of connect that shows the basic idea of what connect actually does. Meanwhile, the real React-Redux library is highly optimized (and does actually use setState internally once it knows the data has really changed).
Finally, while you can create multiple stores, the Redux FAQ advises to only use one store, for several reasons.
I recently published a presentation that introduces the basics of React and Redux. You might want to read through that. I'd also encourage you to read through the Redux docs thoroughly.
Also, I keep a big list of links to high-quality tutorials and articles on React, Redux, and related topics, at https://github.com/markerikson/react-redux-links . Specifically intended to be a great starting point for anyone trying to learn the ecosystem, as well as a solid source of good info on more advanced topics.

If GraphQL and Relay are non-negotiable, does it follow that redux is better left out? Or is there not such complete overlap in concerns?

I've read a lot of heated and contradictory information about this sort of subject and I have no dog in the fight - I have the advantage of an open mind.
Let me walk you through my very informal thought process that led me to think, after using a boilerplate with everything in the relay kitchen sink, that I still needed something like redux.
In more than a few scenarios, sufficient redux boilerplate takes less time and much less thought than the sufficient GraphQL and relay boilerplate
The abstraction of actions in redux is a good thing that keeps many programmers out of trouble by forcing them to separate concerns and to encapsulate the internals of a request / how it works vs the existence of one.
Specifically, if I am making a canvas editor with lots of tools and brushes, it seems like it would take a long time to get started the right way in relay making all those mutators and queries and so on with care for persistence.
But if I say, you know, I don't need my app to know every state ever of everything, without something like redux, there is no alternative to either managing state via some sort of big container object or winging it, both of which are inferior to redux
Therefore my instinct that redux has its place in this scenario is the right instinct
However, I might just not understand how GraphQL and relay are supposed to be used.
Therefore, I am asking for concrete answers about 1) whether this is a fairly objective or subjective question, 2) whether there is a consensus or not, and 3) if I should care.
One more thing - if it is the case that redux is fair game in such a scenario, is it still a good rule of thumb that my app ought to have a single store? Or can I start using redux more modularly and in mroe of an adhoc fashion?
By the way here is a more simple scenario: I want to use a Stepper from material-ui which requires State. Without redux my choices are either to faithfully do that at the relay level or below, wing it in the components, or try to fudge it somehow or mix it. The only sound option is the first, and that takes time.

Resources