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?
Related
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.
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.
I'm developing Web project with react.
But bigger code size the speed is slower. And All code in one system is easy to be complicated and hard to maintain
Is there a way develop by each component with redux, side effect all in one module?
For example, modulizing one component(comtainer) with is's action, stores, side effect. And attach main code with build system..
At the end of the day, a single store will contain all state in redux. The exception to this, is if you choose to run two seperate apps on the same page - but they wouldn't be linked in any way whatsoever (so ignore it).
However, you can use combine reducers to join reducers from multiple components into one store while keeping them separate. For the majority of apps this will suffice completely, and I would find it hard to imagine it would cause performance issues unless it is set up incorrectly.
Your question doesn't lend itself to one concrete answer, but rather patterns. I would look into "ducks" for redux - its not a technology or library, but rather a pattern for keeping your stores and components modular.
Ducks: https://github.com/erikras/ducks-modular-redux
Explanation: https://medium.com/#scbarrus/the-ducks-file-structure-for-redux-d63c41b7035c#.36dsdqd5q
Personal favourite structure doc: https://hashnode.com/post/tips-for-a-better-redux-architecture-lessons-for-enterprise-scale-civrlqhuy0keqc6539boivk2f
If you still feel like redux doesn't align to your modular app, you can consider not using it - sometimes there is no need for it. https://medium.com/#dan_abramov/you-might-not-need-redux-be46360cf367#.p7j6cioou
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.
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.