Should large amounts of data go in the app state in redux? - reactjs

Let's say I have some data tables, like a list an admin report returning a list of users (with details) or a list of log records. Does this info belong in the redux store, where only the data table needs this info? Or what if I am plotting something with 5000 nodes. Does this belong in redux single app state too? Why or why not?
If these items do not belong in the app state, is it just the local component state I should be loading these into without redux? Seems nice to have all my async requests fetched similarly, though.

Since redux doesn't care about the data (it literally just calls reducer functions when actions are dispatched, and replaces the current state with the result), there shouldn't be any performance issue there. It will be as performant as the reducer functions you provide.
If you'd like to see for this directly: https://github.com/rackt/redux/blob/master/src/createStore.js#L115
You're more likely to run into performance issues with react, but even then its doubtful at that scale. You may want to virtualize your table so that you're not rendering out of view elements, but that's a common problem with ui programming.

Yes, the Redux way is to put all your client-side state in the Redux store. See the Three Principles of Redux, the first one in particular:
Single source of truth
The state of your whole application is stored in an object tree within a single store.
This makes it easy to create universal apps, as the state from your server can be serialized and hydrated into the client with no extra coding effort. A single state tree also makes it easier to debug or introspect an application; it also enables you to persist your app’s state in development, for a faster development cycle. Some functionality which has been traditionally difficult to implement - Undo/Redo, for example - can suddenly become trivial to implement, if all of your state is stored in a single tree.

Related

how to manage complex redux state for different async calls?

I have always thought about this question when you have a scenario with a redux slice and you want to fetch multiple different APIs or do some async calls on some events simultaneously, how would you build your reducer and redux state?
let me explain an specific scenario:
Imagine I want the result of 2 APIs and I have this state:
{
data1: null,
data2: null,
loading: false,
error: false,
}
And I want to fetch two calls to get the data on react component mount, should I declare two loadings for these two calls or what? what is the best practice on these kinds of stuff? you can also imagine two or three different event clicks which call an async Fetch API too.
What is the best practice on these kinds of stuff?
There really isn't one, because the answer depends a lot on opinion, architecture vision and specific scenario. In broader sense, this leads to questions like whether to fetch data in react or redux in the first place and it is the reason why there is so many state management libs etc.
I think, especially today, that developers picking redux & its middleware to handle fetching do so often because they prefer to think of all data received from backend as a global state - hence the use of global state management library. That way we can make any such data easily available to any part of our application, whether it is the view layer like react or some logic layer like redux sagas.
With the above in mind, it would make sense to structure the state of the data and metadata (like loading etc.) to make sure it really is easy to access and reuse at any place - and so in your case, to keep the loading/error state for each such slice.
At the same time, maybe you are reasonably sure that two slices of data are only ever going to be used together and so having extra metadata is a waste of time, so as I said in the beginning it all depends also on a specific case from all kind of perspectives.
Also, if all you use sagas for is fetching, something like react-query or rtk-query (if you want global state management for other things) might be a better pick and would make some of these architecture decisions much easier as those libraries are much more opinionated. Don't get me wrong, sagas are great and I personally prefer them in most cases to all the other solutions, but they do require in my experience a strong vision and firmer grasp on your app architecture.

Why can’t we use GraphQL just with Redux

I’m wondering why people doesn’t seem to use GraphQL jus with Redux.
I’ve never used GraphQL before but I’d like to start a new project, but neither Apollo and Relay doesn’t convince me. Currently I’m creating an app that use react and redux and “old fashion” rest api. And I love the idea of redux that it store whole informations about my app in one place.
And now, as far as I understand both Apollo and relay does something similar but they use separate store and in both we mixing the logic and view even more than with just React, both of these things (another store and mixing code) seems to be a bit messy. The advantage is caching, am I right?
So why can’t we just send the query as we used to with normal rest api and put the data to the redux store (maybe try to store some kind information about sync for optimisation).
Sorry if there are thing that i missed, I’m new here and I’m not a pro, it’s why I ask some people that probably has more experience that me :)
"store some kind [of] information about sync for optimisation" becomes a very hard problem when you have lot of interdependent entities.
Also, structuring the client side state is a hard problem in large applications. The rules of thumb, considered as best practices, in the redux community are that you need to normalize and remove redundancy in your redux state tree when inserting and denormalize them when using in components.
The libraries like relay and apollo want to own the state they manage so that they can remove this responsibility of normalizing/denormalizing the data, and managing the cache (as much as possible) to a significant extent from end users while still providing them low level control when they need to.
This is a fairly sophisticated problem because different components may depend on partial models eg. NoteSummary component may need only title and tags fields, the NoteDetails component will need description and comments too.
If you manage the redux state yourself you will have to write code for the following, when NoteDetails component is presented:
If a Note is not already present in the redux tree, fetch the required fields using a graphql query.
If a Note is already present, but not all the required fields are present, create a graphql query for the missing fields, and then fetch them by querying the graphql server.
If a Note is already present, and has all the required fields, just use the local version.
This becomes a lot more complex when we have entities which have dependencies on each other, or when realtime collaboration or subscriptions are involved.
GraphQL libraries attempt to solve all of the above in a very network efficient manner. Using react-apollo or relay your component can declare what all it needs and the underlying library, will intelligently figure out what and how much to fetch.
This is philosophically similar to how you write react components: In your render method you declare what your final component hierarchy should look like (given present state) and the library (react) figures out what changes are to be made to the DOM.
You should evaluate if your use case benefits from this kind of network efficiency and if so, whether you are willing to invest time putting in the effort required to learn GraphQL and the ecosystem around it.
If a redux store and a few ajax calls suffice for your use case, it can be a much simpler setup.
If you decide to go full on with GraphQL and Apollo, you might want to not have redux at all. You can use apollo-link-state and manage all your data (local or remote) using graphql Queries and mutations. Then from the perspective of your components it becomes irrelevant whether some data is remote or local.
Having said all the above, if you really want to just use redux along with graphql without any additional libraries like Relay you can use Apollo client directly. You can dispatch thunks from components, then in your thunks, you can make graphql queries directly using the Apollo client, and once you receive the response you can put that data in the tree in the tree using another action dispatch.
If this sounds more complex, it is because it simply is.

Application design: how much Redux state?

I am currently working on building a small-ish app (6 front-end container-style components, 15 backend DB tables), in React.
I'm playing around with importing Redux, and I'm having a hard time designing my application state. It seems that I'll need to store broad-based state (e.g. user sessions) into Redux, but most of the other state I'll be pulling from the backend and won't necessarily need it to be always up-to-date 100%.
Based on all of the "redux-todo" style examples out there, it would seem that folks would store everything in their Redux store (since the state is relatively small, I suppose).
However, for my case, I'm wondering if Redux should just be a super lightweight store for only that which needs to be persisted across the app, a la an Ember-style 'service'.
Am I thinking about this correctly? Or should I be looking to store more state inside Redux?
I've struggled with that exact issue. It really takes some getting used to, but as another answer said, if you're using Redux, the idiomatic approach is to store basically everything in the Redux store. The one exception (and these turn out to be rather rare) is UI-only data such as a visibility toggle or dropdown info that sets a class or the like. That is, data that is ephemeral and has no impact on anything outside the component in which it lives. Even then, you will find that some UI-only items are easier to manage using actions and reducers as they often end up touching other items.
Edited to add: as the comment below states, the official Redux docs don't take a position on this issue. Which is one reason why so many people struggle with these issues -- you have a ton of freedom how to structure your React/Redux apps. My advice should be understood to be advice based on the experience of trying different approaches. Here are the three main reasons that I've seen for putting state into store:
more often than not, something I put into state ended up being needed somewhere else and getting it there through props required more work than if I had just put the data in the Redux store to start with.
Additionally, it's common to refactor your app to split apart components into more modular reusable pieces as your app grows and gets more complex. If you have data in state that is used in two places in a component you then won't be able split that component into smaller pieces easily.
Finally, readability. It's nice to be able to glance at your mapStateToProps call and see exactly what props are received or used by each component.
The problem is that Redux and putting everything in the store can feel like a lot of unneeded complexity when the actions and impact of the items is simple. If that's the case, I would suggest you consider dropping Redux at least at first. It will be a lot of work to refactor, but it will help you appreciate just where Redux shines. On the other hand, you may in fact not really need it for your app.
Back to your original question, yes, in my opinion, you should be putting more in the Redux store. Everything goes in there with a few very narrow exceptions. Data from the backend in particular should go into the store as a first step before getting mapped to props in the components where it's used.
The idea is to store any state your app needs to function. Your React components don't know anything about data other than what to do with it once they have it. The React/Redux "way" is that the only way they get it is from your Redux store.
So if you're fetching a list of items on app load, that goes in your store. Then your app has it for the entirety of the session. If someone leaves and comes back, or reloads the page, it fetches again, and stores a fresh copy in Redux again. You may not create any actions to modify it once it's there, and you may not need to fetch it again any time soon, but that's where it should live so your components can get stuff from it.
If you didn't store it in Redux where would you put it? And how would your components gain access to it?

React/Redux concept Vs server call requests

I am wondering what is the best design approach between using a big state (store) and sql request in database.
Let's say you have a Todo CRUD application. You can save the Todos list in store within Redux implementation. What is the best approach if you want to make complex statistics on those TODOs: Reducers or sql requests?
For example, you want to get all todos for the current month:
Reducers/store approach
You can get all the todos list from the store and filter todos by date to get all todos for the current month.
Pros:
CRUD actions easy to manage, one state changes in the store (todos list)
Low client/server traffics
Cons
Business logic on client side
client overhead for large data processing
Sql request approach:
Complex request in database to get those todos and save the state 'currentMonthTodos' in the store. In this case you get your current month Todos list from currentMonthTodos state
Pros:
Business logic on server side
Reducing page load time for large datas
Cons
Poor state management for CRUD actions
High network traffic
Size of the store grows up
Let's say you have a Todo CRUD application. You can save the Todos list in store within Redux implementation. What is the best approach if you want to make complex statistics on those TODOs: Reducers or sql requests?
Usually, real life applications you do with the Redux are medium or large scale. Simple CRUD applications you could do either way.
I guess when you mentioned the database (SQL requests) you considered Restful programming.
For the very simple applications, the Redux pattern doesn't have that much sense, unless you need advanced visual effects.
However, small applications do grow over time and can become medium scale fast, by adding more components.
Redux idea is excellent in cases we have a great number of application components that interact. In Redux these will be called the container components, and these are different from the simple presentational components that are also known as stateless functional components.
Having 2 components A and B you have just a few possible update chains.
A will update B and B will update A, or self-update (not including in here the possible updates from outside of the app).
With just three components interacting we have much more possible chains.
And with even more components it gets complicated. We eliminate the possible exponential interaction complexity with the Redux pattern. Redux pattern is similar to 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.
We get very similar to the event driven approach in GUI applications — when you move the mouse you get the events.
In React components create actions. Sometimes a lot of actions. In fact, you may get so many actions in some cases so the application will freeze if you have the bad design.
Typically components should throttle the actions and there are great solutions in React for that.
So what are components in React Redux? From one side components are action dispatcher and on the another side they get the props, possible context, possible the application state or even local state. Finally, components may have the rendering logic. Sometimes components are just containers.
I just wrote this to represent the initial complexity of the Redux pattern while Restful applications are by design simple.
I think that this is the main factor you should take into account. Using Redux for the trivial TODO applications that will never grow the complexity may not be needed, so you may go with the Restful app.
https://egghead.io/lessons/javascript-redux-store-methods-getstate-dispatch-and-subscribe?course=getting-started-with-redux

Redux actions/reducers vs. directly setting state

I'm new to Redux. I'm having trouble understanding the value of actions and reducers vs. components directly modifying the store.
In Redux, your React components don't change the store directly. Instead they dispatch an action -- sort of like publishing a message. Then a reducer handles the action -- sort of like a message subscriber -- and changes the state (more precisely, creates a new state) in response.
I feel like the pub/sub-like interaction adds layers of indirection that make it harder to understand what a component is actually doing -- why not just allow components to pass new state to the Redux store directly? Would it be a bad thing to inject something like this.props.setReduxState into a React component?
I'm starting to understand the value of why the state itself needs to be immutable (related question -- Isn't Redux just glorified global state?), related to checking for updates to see which component props need to be updated in response to state changes. My question is the extra action/reducer layers vs. manipulating the store directly.
I had some very similar questions when I decided on going down the Redux rabbit hole. In my case I was developing relatively small apps and components using just the React internal state, which still works really well. It was only when the app and the number of components grew much larger that setState became somewhat unwieldy.
I don't think this is emphasized enough - you don't always have to use Redux if you're working on a relatively small app or a few components that are easy enough to keep track of without a robust immutable store solution. There is a lot of necessary boilerplate just to get started, which can be overly time consuming in some instances.
That being said, React + Redux is a great design paradigm to follow once you are used to it and have your own boilerplate you can call upon. Redux essentially favors props over state, which forces immutable design as you (generally) can't mutate props. This is what makes the Redux DevTools "time machine" possible, along with all of the middleware that you can throw at your store as previously mentioned by others.
Middleware is a big part of it, especially with the advent of more precise solutions for sync and async tasks alike like redux-saga (https://redux-saga.js.org/). IMO "thunks" (https://github.com/gaearon/redux-thunk) are easier to grok than sagas when you're just getting started, unless you're already an expert with generators, but sagas are much more predictable and therefore testable in the long run.
So instead of having a separate internal state for each component, you can have a set of actions / reducers that you use instead, knowing that you can't mistakenly mutate the state. I've found the combination of ImmutableJS (https://facebook.github.io/immutable-js/) and Reselect (https://github.com/reactjs/reselect), which gives you composable selectors - to be great for this. No need for Object.assigns or tons of spread operators, it creates a new object for you.
I wouldn't be in a hurry to convert existing non-Redux projects into Redux, the workflow is different enough to cause significant confusion, but you'd be hard pressed to find boilerplates for new projects that don't already have Redux in their workflow. Such as "React Boilerplate" (https://github.com/react-boilerplate/react-boilerplate), I know this kind of blew my mind at first, but definitely worth getting a feel for. It really tests your functional programming chops.
In the development process, you often need to know who and how has changed the state. Mutating state by emitting actions allows you to keep answers to those questions.
Actions are payloads of information that tell the store how it should be modified. This information is represented in form of plain javascript objects which allows this information to be logged, serialized and stored. Since all the history is "remembered", you can later replay all the chain of actions for debugging or testing purposes. Together with a tool like Redux DevTools it makes development process really easy and amazing. Since all the store modifications are logged to a monitor, so you can see how and when was the state modified on every step. Even more, you can go back or forward through the actions chain.
Another benefit of having all mutations centralized in one place is the fact that it's easier to take control over the state. That guarantees, that all mutations happen one by one in a strict order and no callbacks can make the application behavior unstable. It also allows to keep in one place functionality that is common for some actions, or in other words to apply middlewares.

Resources