How to deal with component state with redux? - javascript

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 .

Related

React Component State management using redux

So Basically, I came across many articles where they are referring to manage state via flux or redux.
I wanted to know that how about UI component having its own state? Is it good practice to let redux manage the Api call and success toast messages etc. but UI components should have their own local state?
Kindly someone elaborate what is the best practice in industry?
Though the question calls for opinion, I am going to leave my answer. There is no standard best practice regarding this. It boils down to convenience and ground rules of your team, if there are more than one people writing the code.
I use Redux quite a lot. However, I won't refrain from using local state in components.
Form handling like input onChange handlers require local state. It is not performant to use global state for onChange handlers.
Reusable component uses local state. Again, it boils down to whether the reusability is a technical reusability or business reusability. If you are developing a custom scrollbar component, use local state. However, if you are using a comment form which is used everywhere in your application, use global state.
I prefer to have most of the stuff in global state. I use redux thunk as well. In redux thunk, it is possible to access global state within the thunk function. This is quite useful as it avoids the reliance for props / context being passed all around.
I do keep some simple things in local state -- for example, show / hide some stuff. I don't mind waiting for promises to resolve before hiding some stuff using local state.
Overall, the decision to use global state vs local state is primarily based on convenience. There are no standard rules other than what you and your team are comfortable with.
React is a way to declaratively deal with UI. There are some rules of the framework like state, props, context. It is left upto the developer to make the UI declarative and performant based on these primitives. How, a developer does it does not matter as long as the code is maintainable and understood by others.
After asking many professionals and industry developers, I came to know that managing state through redux depends on your application scope.
but more importantly, If I am working on enterprise Application then the application state must be managed through redux.
Now the question is what should be kept in our redux store. well, you can store almost anything in redux store but better to manage the local state of a component as well. for instance, opening a component Boolean should be managed in local state or any string or header name etc.
Good question! The answer is usually "it depends", but there are clear cases when you'd probably prefer to use one over the other.
Use Redux for storing state relevant to the application. E.g. the current page/panel that should be shown. As you mentioned, showing a notification/message - is something that'd make sense to store in redux state, as the alternative would be passing state all over the place, e.g. an error prop bubbling up to your root component which renders the toast message. Using thunk is also a good idea when you're fetching/manipulating data relevant to the whole app, e.g. a list of things that appear in several places.
Use component state for storing state only relevant to the component. That is, if you're filling in a form, it makes sense to store the value of text inputs, checkboxes etc. in your component state (perhaps in conjunction with container and presentational components) as the values at this point aren't relevant to the rest of the application.

ReactJS local vs global state and implementing redux at a later time

So we are about two months in on a project. This is the first time I have ever managed code writers and not written the code myself. I've been reading their code for the last week. What was suppose to be a simple React app has turned into a spaghetti mess.
I understand: redux helps to manage global state. But should that mean that all buttons should map to a global "action?" This has seemed to create this entire mess of objects scattered throughout the entire app. I keep asking myself, why are we using global state for everything when local state could be used for 90% of the application. This is the kind of code that gives me heartburn:
let subitems = SidebarItems[state.type].sub_items;
Store.dispatch(SidebarSubItemHandler(item.action, subitems[0], null));
if(item.sub_items[subitems[0]].param) {
browserHistory.push(`${item.sub_items[subitems[0]].path}/${item.sub_items[subitems[0]].param}`);
} else {
browserHistory.push(item.sub_items[subitems[0]].path);
}
subItembuttons = Object.keys(this.props.subitems.sub_items).map(subitem => {
let subItem = this.props.subitems.sub_items[subitem];
return <li className={this.props.activeSubItem.action == subItem.action ? "bottom-bar-item active" : "bottom-bar-item"}
onClick={e => this.props.onClickSubItem(e, subItem)}
key={subItem.action} style={this.props.subitems.inlineStyles.mobileSubItemLI}>
{subItem.item}
</li>;
});
The application is littered with all kinds of objects like these that map to "action" objects. So at this point we are making the decision to scrap the entire project and restart from scratch, but without redux. Let's try to do as much as possible using local state only. When it comes time, and we need global state for something, ONLY implement it for that something, not every single action in the app. Does this make sense?
So I guess my question is: If we develop an app using local state and just fundamental React, will we be creating un-reversable problems that would prevent us from implementing redux on a per item basis?
Quoting from the relevant Redux FAQ entry at http://redux.js.org/docs/faq/OrganizingState.html#organizing-state-only-redux-state:
Using local component state is fine. As a developer, it is your job to determine what kinds of state make up your application, and where each piece of state should live. Find a balance that works for you, and go with it.
Some common rules of thumb for determing what kind of data should be put into Redux:
Do other parts of the application care about this data?
Do you need to be able to create further derived data based on this original data?
Is the same data being used to drive multiple components?
Is there value to you in being able to restore this state to a given point in time (ie, time travel debugging)?
Do you want to cache the data (ie, use what's in state if it's already there instead of re-requesting it)?
Per your specific question: if you use the "container component" pattern fairly consistently, it should be relatively straightforward to swap those "plain React" containers for Redux-connected containers down the line. See https://github.com/markerikson/react-redux-links/blob/master/react-component-patterns.md#component-categories for articles on the "container/presentational component" pattern.
Two other thoughts. First, I recently co-authored an article that discusses why you might want to use Redux in a React application.
Second: yeah, that code looks kinda ugly. I'm hoping those are at least three different snippets from different parts of the codebase, rather than one snippet, but that's rather hard to read. The repeated use of "sub_items" and "subitems" seems like a bit of a red flag, readability-wise.
It also doesn't look like it's following good Redux practices. For example, idiomatic Redux code almost never references the store directly. Instead, references to dispatch and getState are available via middleware, and thus can be used in action creators via redux-thunk and redux-saga. Connected components can also access dispatch.
Overall: you are absolutely welcome to use as much or as little Redux as you want, and as much or as little local component state as you want. I think the larger issue, though, is how well your team actually understands Redux, and how they're trying to use it.

Multiple render variants with React?

I've built a web application using React which is up and running and working well. I should probably just leave it alone, but there's one area which is troubling me, where I think I need to do a bit of refactoring because what I'm doing doesn't seem to me to be going with the flow of React. I'd be interested in others' views.
I have a React class, Product, which I use to keep track of products on the page. The only property stored in state is 'quantity', but I have various functions which do things like update a basket by means of pub/sub. Depending on how and where this Product class is used (whether in a table or for a detail view, whether on mobile or desktop), the necessary display is quite different. So in my render function, I call variously 'renderForDetailOnMobile', 'renderForTableOnMobile', 'renderForDetailOnDesktop' and 'renderForTableOnDesktop'.
As I say, this doesn't feel very React-y to me, as if I've got the whole thing upside down (although the rest of the app is, I would say much more idiomatic). So how should be thinking this through in order to break it down into separate smaller classes, which is what I imagine I should be doing? Sorry, for privacy reasons it's not possible to poast actual code, so I hope this description makes the situation clear enough.
You should be using reducers or stores, depending whether you have a flux or redux application. This would help you to understand your state and how it changes.
I see you are using state in your Product, while you should be using stores as mentioned above.
So, how I see the issue is that you have data source and you need to transform it based on the device requirements.
In such case I would make a container which would load other components in charge of transforming and presenting data for different devices.
Container should be rather simple just returning the correct component based on the conditional being met.

React + Redux performance optimization with componentShouldUpdate

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.

How to handle non-view-altering actions in Flux & React.js

In Flux every action should be handled by the dispatcher.
What about an action that doesn't alter the view or the markup, such as "scroll this element into view"? What is the "Flux-way" of handling such a scenario? To by-pass the dispatcher? Or to handle it in the dispatcher without involving the stores or the components?
Flux is really more about application state management, and is not at all about the details of what components are rendered in the view. That's the domain of React. Flux simply assumes you have some kind of reactive view layer -- usually that's React.
Application state is not the same as component state. Application state is something that needs to be known in multiple components. For component state, React's this.state is perfectly adequate. An input component is a good example of something that might need this.
So in your case, if only one component needs to know the scroll position, there may not be a good case for moving that state to a Flux Store. But as soon as that needs to be known in multiple components -- especially components in different branches of the tree -- you probably want that state being managed in a Store.
The other issue your question raises is the role of Flux Actions. A Flux application always uses Actions as the origin of the data flow. There are a lot of good reasons for doing this: stable application state, keeping the app resilient to new features, keeping it easy to reason about, undo history, reconstitution of application state, stateless view components, etc.
Occasionally people want to write as little code as possible and they use a callback passed between components to change this.state in the parent component instead of dispatching a new action to go through the Flux data flow. I find this to be mixing the view and state management layers of an application, and while expedient, this can lead to a lot of headache. It isn't very flexible in the long run, because now the state is coupled to these few components. Building up a Flux data flow from the start is much simpler in the long run, and much more resilient to new features. That said, it also requires more investment in code up front.
If your app doesn't need to know about scrolling (seems rare that it would), there's no need to fire an action. Since Flux is really there to handle data flow (and subsequent changes based on that data flow), it doesn't need to know about every action that occurs.

Categories

Resources