5 ms·
When do you get to write `a.b = c` in react? Not with `setState`
by gyrgtyn 9y ago
When do you get to write `a.b = c` in react? Not with `setState`
- noncoml 9y agoDon't you use `setState` only for UI state, i.e. react components? As far as I understand it with redux you end up having all of your application's state in the store. Unless you split it?
- acemarke 9y agoIt's up to you how much of your data you put into Redux. Quoting the Redux FAQ at http://redux.js.org/docs/faq/OrganizingState.html#organizing-state-only-redux-state http://redux.js.org/docs/faq/OrganizingState.html#organizing... : > 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 determining 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)? I've seen some people say that you should put literally every single value in your app into Redux. You certainly _can_ do that, but I would see it as overkill. I'm much more pragmatic about it - put it into Redux if it makes sense to, per the rules of thumb in the FAQ.
- noncoml 9y ago> Some common rules of thumb for determining 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)? Won't having half your state outside the store and the other half inside add unneeded complexity and make your code even more difficult to read?
- acemarke 9y agoThe most common (and to me, reasonable) situation would be to keep all fetched data in Redux, any other app state that needs to be referenced by multiple components, and possibly some bits of UI state as needed (like "currently showing a modal for editing an item"). Component state would be primarily used for "is this dropdown open"-type values. But, as I said, it's totally up to you to decide what lives where :)
- ramses0 9y agoAnother way to look at it: What data is OK to lose if you refresh the page? That to me is component state. You don't have a url: '.../?dropdown.001=open' / '.../?dropdown.001=closed' so that's likely purely component state (not application state).
- acemarke 9y agoVery good point. Ditto with hot reloading components. React-Hot-Loader tries to retain component state via complex use of code transformation and "proxy" components, but it's very finicky and has lots of edge cases. Using the "plain" HMR API to just swap out the entire component tree on any component change is much simpler and more reliable, but doesn't preserve component state. Choosing to keep something in Redux so that it gets retained during that situation is a valid choice.
- alexanderchr 9y agoIt really depends on what you do. If you use component state in high-level components and pass it around a lot, yes it will likely lead to hard to understand code. But I see no issue with using state for state internal to low-level components, like an input field's value or whether a paragraph with a 'read more' button is expanded. Of course, once you need to access a piece of state from outside that component you should probably move it to the store. But until then you are just creating unnecessary complexity by cluttering global state.
- josephorjoe 9y agoYes. And it usually isn't anything as sane as half in the store and half in one other place. It's like 70% in the store, and 5% in component#1, and 8% in component#2, and 16% in component#3 (duplicating some stuff from component#1 and sorta duplicating some stuff from component#2 with some notes that someone should refactor all this and move those to redux) and the rest of it is only god knows where. And then there is some hard to track down UI bug because using setState() turns out to be really much slower than you think it is going to be. But Redux is so boilerplatey and heavy handed that it made sense in each individual case to the original coder/reviewer to not use it.
- acemarke 9y ago`setState` doesn't actually care whether you've mutated your data or updated it immutably. In fact, I just ran a quick test, and you can even directly mutate your state object and then call `this.setState({})`, and it will update. `setState` is basically a combination of "queue an update to `this.state`, and queue a re-render along with that". So, if you mutate `this.state` and then re-render, your render output would be "correct" because the state object was updated. Where immutability really comes into play with React itself is optimizations via `shouldComponentUpdate`. The fastest way to determine if a component needs to update is shallow equality comparisons of current and next props/state, which requires that you do immutable data updates to produce new object references. Two good articles on the topic are [0] and [1]. [0] http://reactkungfu.com/2015/08/pros-and-cons-of-using-immutability-with-react-js/ http://reactkungfu.com/2015/08/pros-and-cons-of-using-immuta... [1] https://www.bennadel.com/blog/2903-why-should-i-care-about-immutable-data-in-reactjs.htm https://www.bennadel.com/blog/2903-why-should-i-care-about-i...
- amk_ 9y ago> setState doesn't actually care whether you've mutated your data or updated it immutably. Not necessarily - if something downstream is looking at the values (such as a shouldComponentUpdate check), the first mutation may cause the current value to === the next value and prevent a render. I know you called this out as an "optimization" but you don't always know what's happening inside your components, especially if 3rd party libraries are involved.
- acemarke 9y agoThat's what I was saying. The actual `setState()` function can be called with new references from immutable data, the same references that already existed but were mutated, or even no references at all if you mutated. So, literally, `setState()` does not care what process you used to potentially update data before calling it - it just applies a shallow merge of whatever object you passed in to the existing `this.state` object, and then queues a re-render. It's the _rest_ of your code that might care. The primary reasons to actually update data immutably before calling `setState` are for easy and consistent implementation of `shouldComponentUpdate` / use of `PureComponent`, and general FP principles that immutability should be preferred over mutation.