You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Use React for ephemeral state that doesn't matter to the app globally and doesn't mutate in complex ways. For example, a toggle in some UI element, a form input state. Use Redux for state that matters globally or is mutated in complex ways. For example, cached users, or a post draft.
Sometimes you'll want to move from Redux state to React state (when storing something in Redux gets awkward) or the other way around (when more components need to have access to some state that used to be local).
The rule of thumb is: do whatever is less awkward.
stephanebachelier, vnctaing, jmahony, mbeaudru, daletune and 984 morechaosforfun and neaumusicmiclaus, v29neil, borisyankov, joncursi, aaeronn and 140 morevinhlh, kimeshan, JeffOwOSun, davidjsalazarmoreno, benweizhu and 125 moreacasaccia, srosset81, CVarisco, hyukkwonepic, temitope and 26 morescottlazz, freynolds, FerreiraRaphael, mohnish, jsdevel and 156 more
For data fetched via network requests, always use stores in order to support server-side rendering (if you believe that is the ultimate goal), or you won't be able rehydrate.
For those state to be listened by two or more containers, it should also be in stores?
mvalipour, olegdeezus, kunal15595, muaaz-vf, mica16 and 12 more
I agree with @Gaeron about the distinction of ephemeral vs. persistent. But I actually think about this in three categories. One is the UI state that he talks about and I also think of as ephemeral. Another is the application state which is really the persistent core of the application. But a third, which sits in between, is routing state. I use the term "routing" because it is familiar to people, but I abstract this to a "view selection" state since I think that spans desktop, web and mobile better.
Now you could argue that this is UI state because it is deciding what people see (much like the state of tabs, for example). But I see two distinctions. The first is that the state is serialized (i.e., as a URL) and sent to other people. So things should go in the route state if you want people to be able to "deep link" right to that particular UI state. The second is that in many cases the initial route state or a change in route triggers a change in application state (i.e., loading the data to be viewed). Of course, actions in the UI do the same thing. But the distinction I make is that you can (and should) have route state without any view or rendering precisely to test the "application logic" around changes in route state. And it is because the view and rendering don't need to be involved that makes it partly application state, IMHO.
How does this relate to the question of Redux vs. React for state management? Application state is the domain of Redux and UI state is the domain of React. But routing state should (in my opinion) be managed by Redux even though it can be viewed as UI state (see the embedded links for more discussion of why I think that).
To be clear, @gaearon's comment about things moving around still applies. But I just find it useful to distinguish these different cases.
nowinskp, ZackCao, ankitladhania, sunlee-newyork, Tenyoku8478 and 31 moreriyajk, csantiago132, mustafaekim and mxchange
Application state is the domain of Redux and UI state is the domain of React.
Note that I don't claim this. I think it's fine both to keep some app state in React, and some UI state in Redux. I don't think they should be separated by domains.
The way I think about it, if you create an app with Redux, embrace the single state tree. Put UI state there as well. However if it gets tedious and frustrating don’t be afraid to put state into the components. My point is that use single state tree unless it is awkward, and only do this when it simplifies things for you rather than complicates them. That’s the only guideline.
miclaus, Kushagra8888, piecedigital, elliothimmelfarb, echenley and 101 moreYutHelloWorld, x5engine and slowmanchanckeen-amphora, atomicquasar, x5engine and slowmanchan
First, I certainly didn't mean to put words in @gaearon's mouth, sorry for that.
Second, I completely agree with @gaearon. I also believe firmly in a single state tree approach. When I talked about UI state, I had in my mind really minor things (like what is the current tab selected) where it might not really be that relevant to the application state (exactly has @gaearon discussed).
So let me clarify my position. I agree that pretty much everything should be in Redux, including the route state (as I've done in my TodoMVC implementation with Redux and TypeScript. I specifically mentioned route state and distinguished it because I think (and you can see it in that TodoMVC implementation) that it definitely belongs in Redux (and shouldn't be connected at all to rendering) and is most definitely not "UI state".
For React components I rarely use state. I prefer to use props both to get information about what to render and to get closures that I can invoke to trigger changes external to my component. There are some infrequent circumstances where I introduce state in components just to make life easier, but I try to avoid it. I hope that clarifies things.
I think this question is really subjective and complicated, so I made a tough decision with my team today, don't bother:
for non-reusable container, which has connection to Redux, just put everything into Redux store, even tiny UI state like if a modal is open, don't use this.setState any more.
for reusable component, which has nothing to do with Redux, use React state.
And now we're implementing some helpers to make it less tedious to manage tiny UI state.
@inetfuture I tend to be a bit miserly about application (redux) state because I'm using TypeScript and I define a type for my application state all the way down. That being said, I've gotten in the happen when developing component libraries to separate all the state manipulation from the rendering (see links in previous comments for more details). This means that even for general components that aren't trivial, I completely externalize the state. I generally pass everything in through props (both states and closures for manipulating state). That way, I can easily hook it into my application state. Part of this is undoubtedly an artifact of using TypeScript and not being able to just use combineReducers and connect to hook things in (and preserve the type constraints at least). So this is probably not a representative viewpoint. But I will say that why you say "just put everything into Redux store", I would worry that you'll end up with a kitchen sink of state. I think the fact that my use of TypeScript means that it takes some effort to expand application state is not necessarily a bad thing because it forces me to decide "do I really need this?" instead of letting stuff just pile up.
As an alternate thought: local component state can be useful for controlled inputs that need a fast update time, as well as reducing the number of actual actions triggered. In my current prototype, I put together a form-editing HOC that receives the current item being edited as a prop. It also handles form input change events by saving the changed field in its state, then calling a debounced "EDIT_ITEM_ATTRIBUTE" action creator with the combined local WIP changes. The result is that the form fields update immediately, because only the form itself is being re-rendered, and a lot fewer actions are triggered (like, if I held down 'A' for a few seconds, only the 'AAAAAAAAAAAA' value would be sent as an action rather than 'A', 'AA', etc).
As for reusable components, if they are large and complex enough, it would be quite future-proof to have their state in Redux, mainly for traceability and replay for testing. But there are still some doubts on how exactly this code reuse should be architected (components plus actions plus reducers).
I rarely found it awkward to store states in Redux. I like the power it provides, that down the road I can make it interact with some other component if I need it to.
The only thing that’s coming to my mind where it would be awkward is handling the state of form elements, because there can be so many of them. In that case I use a library like redux-form.
Activity
gaearon commentedon Jan 27, 2016
Use React for ephemeral state that doesn't matter to the app globally and doesn't mutate in complex ways. For example, a toggle in some UI element, a form input state. Use Redux for state that matters globally or is mutated in complex ways. For example, cached users, or a post draft.
Sometimes you'll want to move from Redux state to React state (when storing something in Redux gets awkward) or the other way around (when more components need to have access to some state that used to be local).
The rule of thumb is: do whatever is less awkward.
lionng429 commentedon Jan 27, 2016
For data fetched via network requests, always use stores in order to support server-side rendering (if you believe that is the ultimate goal), or you won't be able rehydrate.
For those state to be listened by two or more containers, it should also be in stores?
xogeny commentedon Jan 27, 2016
I agree with @Gaeron about the distinction of ephemeral vs. persistent. But I actually think about this in three categories. One is the UI state that he talks about and I also think of as ephemeral. Another is the application state which is really the persistent core of the application. But a third, which sits in between, is routing state. I use the term "routing" because it is familiar to people, but I abstract this to a "view selection" state since I think that spans desktop, web and mobile better.
Now you could argue that this is UI state because it is deciding what people see (much like the state of tabs, for example). But I see two distinctions. The first is that the state is serialized (i.e., as a URL) and sent to other people. So things should go in the route state if you want people to be able to "deep link" right to that particular UI state. The second is that in many cases the initial route state or a change in route triggers a change in application state (i.e., loading the data to be viewed). Of course, actions in the UI do the same thing. But the distinction I make is that you can (and should) have route state without any view or rendering precisely to test the "application logic" around changes in route state. And it is because the view and rendering don't need to be involved that makes it partly application state, IMHO.
How does this relate to the question of Redux vs. React for state management? Application state is the domain of Redux and UI state is the domain of React. But routing state should (in my opinion) be managed by Redux even though it can be viewed as UI state (see the embedded links for more discussion of why I think that).
To be clear, @gaearon's comment about things moving around still applies. But I just find it useful to distinguish these different cases.
gaearon commentedon Jan 27, 2016
Note that I don't claim this. I think it's fine both to keep some app state in React, and some UI state in Redux. I don't think they should be separated by domains.
The way I think about it, if you create an app with Redux, embrace the single state tree. Put UI state there as well. However if it gets tedious and frustrating don’t be afraid to put state into the components. My point is that use single state tree unless it is awkward, and only do this when it simplifies things for you rather than complicates them. That’s the only guideline.
xogeny commentedon Jan 27, 2016
First, I certainly didn't mean to put words in @gaearon's mouth, sorry for that.
Second, I completely agree with @gaearon. I also believe firmly in a single state tree approach. When I talked about UI state, I had in my mind really minor things (like what is the current tab selected) where it might not really be that relevant to the application state (exactly has @gaearon discussed).
So let me clarify my position. I agree that pretty much everything should be in Redux, including the route state (as I've done in my TodoMVC implementation with Redux and TypeScript. I specifically mentioned route state and distinguished it because I think (and you can see it in that TodoMVC implementation) that it definitely belongs in Redux (and shouldn't be connected at all to rendering) and is most definitely not "UI state".
For React components I rarely use state. I prefer to use props both to get information about what to render and to get closures that I can invoke to trigger changes external to my component. There are some infrequent circumstances where I introduce state in components just to make life easier, but I try to avoid it. I hope that clarifies things.
inetfuture commentedon Jan 28, 2016
I think this question is really subjective and complicated, so I made a tough decision with my team today, don't bother:
this.setState
any more.And now we're implementing some helpers to make it less tedious to manage tiny UI state.
@gaearon @lionng429 @xogeny Any drawbacks you can think of this approach?
xogeny commentedon Jan 28, 2016
@inetfuture I tend to be a bit miserly about application (redux) state because I'm using TypeScript and I define a type for my application state all the way down. That being said, I've gotten in the happen when developing component libraries to separate all the state manipulation from the rendering (see links in previous comments for more details). This means that even for general components that aren't trivial, I completely externalize the state. I generally pass everything in through props (both states and closures for manipulating state). That way, I can easily hook it into my application state. Part of this is undoubtedly an artifact of using TypeScript and not being able to just use
combineReducers
andconnect
to hook things in (and preserve the type constraints at least). So this is probably not a representative viewpoint. But I will say that why you say "just put everything into Redux store", I would worry that you'll end up with a kitchen sink of state. I think the fact that my use of TypeScript means that it takes some effort to expand application state is not necessarily a bad thing because it forces me to decide "do I really need this?" instead of letting stuff just pile up.markerikson commentedon Jan 28, 2016
As an alternate thought: local component state can be useful for controlled inputs that need a fast update time, as well as reducing the number of actual actions triggered. In my current prototype, I put together a form-editing HOC that receives the current item being edited as a prop. It also handles form input change events by saving the changed field in its state, then calling a debounced "EDIT_ITEM_ATTRIBUTE" action creator with the combined local WIP changes. The result is that the form fields update immediately, because only the form itself is being re-rendered, and a lot fewer actions are triggered (like, if I held down 'A' for a few seconds, only the 'AAAAAAAAAAAA' value would be sent as an action rather than 'A', 'AA', etc).
I've got the HOC up as a gist over at https://gist.github.com/markerikson/554cab15d83fd994dfab , if anyone cares.
Anyway, the point is that that component state and store state both have their uses - you just gotta consider your actual use case.
sompylasar commentedon Jan 28, 2016
As for reusable components, if they are large and complex enough, it would be quite future-proof to have their state in Redux, mainly for traceability and replay for testing. But there are still some doubts on how exactly this code reuse should be architected (components plus actions plus reducers).
galkinrost commentedon Feb 14, 2016
In our applications we solved this problem in connect-like style. https://github.com/Babo-Ltd/redux-state
silvenon commentedon Feb 20, 2016
I rarely found it awkward to store states in Redux. I like the power it provides, that down the road I can make it interact with some other component if I need it to.
The only thing that’s coming to my mind where it would be awkward is handling the state of form elements, because there can be so many of them. In that case I use a library like redux-form.
36 remaining items