-
-
Notifications
You must be signed in to change notification settings - Fork 350
observer: props is, itself, observable when only each prop should be #347
Comments
Could you setup a fiddle / sandbox demonstrating this issue?
Op do 19 okt. 2017 om 00:35 schreef Adam Abeshouse <notifications@github.com
…:
@observer
class Person extends React.Component<{ firstName:string, lastName:string }, {}> {
render() {
return <span>{this.props.firstName}</span>;
}
}
This will rerender when props.lastName changes, even though there's no
need for it to, because this.props object has an atom associated to it that
reports change
https://github.com/mobxjs/mobx-react/blob/master/src/observer.js#L143
This makes using props quite unwieldy - in order to avoid this issue I'd
need to wrap every prop access in a @computed to prevent rerender unless
the value changes.
For example, this works as desired/expected:
@observer
class Person2 extends React.Component<{ firstName:string, lastName:string }, {}> {
@computed get firstName() {
return this.props.firstName;
}
render() {
return <span>{this.firstName}</span>;
}
}
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
<#347>, or mute the thread
<https://github.com/notifications/unsubscribe-auth/ABvGhHtvElyA2kDDxQbmShwO_9x3ohXBks5stn1IgaJpZM4P-dFk>
.
|
@mweststrate sorry for the sloppy initial query, please see my updated post above. |
The problem is that props object is immutable and the whole props object is replaced when new props arrives. The props are not updated individually, therefore making them observable is useless. |
@urugator that's a good point. However, even so, it could be accomplished using getters and setters. |
It could also be accomplished by having an observable props object which is, key by key, updated w the values of the immutable object coming in. |
Prop keys are dynamic, keys of observable object not... |
This could be handled with |
How? You need to translate |
EDIT: @urugator pointed out this wouldn't work, please see updated proposal. Actually,
|
You need to "subscribe" also for prop keys, which were used in render, but weren't passed by props yet. These keys should be observed, but are not installed yet, therefore the subscription won't happen. |
Good catch. I wasn't aware of this functionality but it looks like you can also define getters with computed property names. So here's an updated (simpler) version that handles the issue you raised - an atom is created the first time the key is accessed or set, and
|
Computed prop name is not a param passed to function. It simply means that you can do this: let propName = a ? "a" : "b";
const o = {
get [propName]() {....} // propName must be defined here
} The Proxies are the only way to do this. |
@urugator ah my mistake. Yes Proxy seems to be what I'm looking for. I think it's clear that would be possible with not much change to the code I've written above. In my opinion this is the way observable props should work - I can't think of a case where someone would want to observe changes to props without observing changes to a particular prop, and by observing changes to particular props we get the fine-grained behavior we need for the application I brought up in my OP. The only potential pitfalls as I see are that (1) This is more computational work on prop access and on setting props, but that may be negligible, and (2) That this would be a breaking change. (2) could be solved by adding a decorator argument to determine "observable props mode", to maintain backwards compatibility. |
Unfortunately, we can't use Proxy currently. Note that what you do is not a typical or recommeded usage. Which doesn't mean that it can't be useful in some situations... |
That makes sense, thanks for your responses. |
EDITED because original query was not coherent:
In this jsfiddle, there's a toy model of a scenario I'm facing: I have multiple subcomponents in
render
which I want to not re-compute unnecessarily, and I was hoping to be able to use the observable nature of props together with the Observer tag to implement this. However, because its not the properties of props which are tracked, but the reference tothis.props
itself, both subcomponents will recompute every time any props change, regardless of which props are actually used in each subcomponent.The class in the fiddle is duplicated below:
There are two possible solutions to regain the desired functionality:
(1) Use components (decorated with
@observer
), and pass in desired data through props, in order to regain the shallow comparison functionality inshouldComponentUpdate
, e.g.(2) Wrap all prop accesses in
@computed
's, e.g.Both are more unwieldy than if the props object were observable, thus each prop tracked individually, instead of the reference to the props object.
The text was updated successfully, but these errors were encountered: