Taking some hard perspective from Redux, should a component's state be immutable by default, or would that be too much overhead for React?
Side note, and possibly previously addressed topic: Shouldn't setState() be immutable by default? I realize there are immutability helpers, but _man_ that syntax is hard on the eyes.
Not so much "sugar" as "vinegar". :) I also know there is a section on Immutability.js on the Advanced Performance page, but it doesn't address setState() directly.
It's not clear (at least to me) from the setState() docs whether React already handles this.
returns an object
👍containing keys to update.
❓
Sorry for the sidebar. Just wanting to get a confirmation either way.
https://github.com/facebook/immutable-js/wiki/Immutable-as-React-state
Probably too much overhead, the lack of immutability also enables some potential performance improvements so personally I'm inclined to say no. But I haven't thought about it as much as @sebmarkbage so I'll let him chime in.
Generally if you want to make use of immutable-js, we say to store the value in state (eg setState({data: new Immutable.Record()}). I realize we don't actually say that explicitly in the docs but that's the intent (and what immutable-js does in that wiki).
And just ignore the immutability helpers. They don't belong in React. They are interesting on their own and can be used in conjunction but are probably not the way we should encourage immutability. You would use them the same way though, having some field in state that points to the result of an update(this.state.data, ...) call.
Do you mean React state should be immutable as in Object.freeze(this.state) or do you mean immutable as in an "immutable-js" Record data structure with the update method?
I don't think we can't take on immutable-js as a hard dependency. It is unclear if that's the end all way to treat immutable records anyway.
We could make this.state immutable since React recreates it whenever you call this.setState(...). This is something that would be nice to have for clarity. I'm not worried about perf implications. The perf win you get from allocating at this one level is negligible. However, at the same time mutation is very convenient when you do things like this.state.counter++; this.forceUpdate(); so not sure if it is worth breaking that.
Deep immutability is another thing. That is kind of tough because lots of data structures require cyclic dependencies or external dependencies. Currently I think it is too early to go all in on deep immutability. So why enforce this on only one level deep?
@sebmarkbage IMHO it seems state could even be considered a component-internal implementation detail, given the right life-cycle methods right? I.e. such that you could implement a MutableStatefulReactComponent/ImmutableJsStatefulReactComponent/etc base class/helpers (while ReactComponent does not provide state) yourself and use as you see fit. There's no major reason beyond "(unreasonable?) complexity" that state is formalized in this way right? And possibly overhead to some degree, although I imagine that wouldn't be an issue in practice.
@sebmarkbage Something like Object.freeze() doesn't seem like too much overhead. We're already doing it for props right?
@milesj I think the issue is that Object.freeze(this.state) is shallow; it doesn't prevent you from doing stuff like this.state.data.field = ...;. So we'll need to recursively deep freeze the state object, which doesn't really work (or has too much overhead) when the state contains circular references.
IMO way too much overhead. Also keeping it un-opinionated is at the core of it all.
We could make
this.stateimmutable since React recreates it whenever you callthis.setState(...).
Exactly.
@sebmarkbage @keyanzhang It's less about recursively deep freezing, more about serializing state at init, and only diffing thereafter. Then there would theoretically be no need to "recreate" it.
Most helpful comment
Probably too much overhead, the lack of immutability also enables some potential performance improvements so personally I'm inclined to say no. But I haven't thought about it as much as @sebmarkbage so I'll let him chime in.
Generally if you want to make use of immutable-js, we say to store the value in state (eg
setState({data: new Immutable.Record()}). I realize we don't actually say that explicitly in the docs but that's the intent (and what immutable-js does in that wiki).And just ignore the immutability helpers. They don't belong in React. They are interesting on their own and can be used in conjunction but are probably not the way we should encourage immutability. You would use them the same way though, having some field in state that points to the result of an
update(this.state.data, ...)call.