-
-
Notifications
You must be signed in to change notification settings - Fork 9.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix knobs for React < 16.3 #3866
Fix knobs for React < 16.3 #3866
Conversation
The `getDerivedStateFromProps` lifecycle method was added in React 16.3, and older versions of react won’t execute it. Many of the knob components were relying on this function to initialize component state, and so in older versions of react state was undefined, and grabbing `value` would blow up. Most of the usages in these components were to memoize props, but that can be handled more cleanly through the use of `PureComponent`, as mentioned in: https://reactjs.org/blog/2018/06/07/you-probably-dont-need-derived-state.html#what-about-memoization
I also pushed a commit in an attempt to fix the error I got from CircleCI about a dirty repo. I don't see how this could be related to any of my changes, but maybe??? |
@@ -10,28 +10,18 @@ function formatArray(value, separator) { | |||
return value.split(separator); | |||
} | |||
|
|||
class ArrayType extends React.Component { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure how useful PureComponent
is here.
Since knobs
is a object, shallow comparisons done by PureComponent
are always going to return false
. and maybe will even have a slight performance hit since we're always doing a shallow comparison of prop values
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, yeah I'm not so familiar with the inner workings of knobs
. Are you saying that the knob
prop is re-generated very often (each time this component re-renders)?
Perhaps a better solution would be a custom shouldComponentUpdate
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I mean that using PureComponent
is unnecessary since the shallow comparison of props (in this case this.props.knob
) is always going to return false
Thus they should remain Component
There is no need for an implementation of shouldComponentUpdate
After minor comment is addressed LGTM |
It seems that some were not being accounted for.
Because the `knob` object prop is being regenerated each time the parent re-renders, we can’t use the shallow prop comparison that PureComponent does. So this uses a `shouldComponentUpdate` instead, which in most cases just compares the `knob.value` prop to see if it has changed. I don’t believe that the `name` is changed between renders. Same goes for number range configurations and array separators.
Codecov Report
@@ Coverage Diff @@
## master #3866 +/- ##
==========================================
+ Coverage 41.44% 41.55% +0.11%
==========================================
Files 455 455
Lines 5193 5176 -17
Branches 903 898 -5
==========================================
- Hits 2152 2151 -1
+ Misses 2496 2485 -11
+ Partials 545 540 -5
Continue to review full report at Codecov.
|
As @wuweiweiwu pointed out, it's not possible to rely on I did a little experimenting, and sure enough the components were re-rendering when a different knob was changed. So I added a |
@IanVS I think you shouldn't implement Since each component is being recreated every single time a value changed. |
When I tested it, the @ndelangen has done a lot of performance work on these components, perhaps he has some insight here? I'm happy to take them out if that is the consensus, but I would hate for this PR to have the end effect of harming performance for all users (since it will be removing the memoizing effect of |
@IanVS I'm not sure what you mean by the memoizing effect of Unless you're implementing
I hope my point is clear. I'm happy to answer any questions. edit: to clarify. I think your current changes is good |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Performance seems really good in the official example so LGTM @IanVS
I'm a bit concerned that the changes here will prevent renders if the name of knobs is being dynamically changed (which seems like a weird thing to do, but maybe there's a use case?) I can submit another PR to address that requirement if desired. Barring that, is there a chance to get a new alpha release? Our stories are currently broken until this can go out (I can't figure out how to point our app at my own fork, since it's a lerna project). |
Released as |
Issue:
The
getDerivedStateFromProps
lifecycle method was added in React 16.3,and older versions of react won’t execute it. Many of the knob components
were relying on this function to initialize component state, and so in
older versions of react state was undefined, and grabbing
value
wouldblow up.
What I did
Most of the usages in these components were to memoize props, but that
can be handled more cleanly through the use of
PureComponent
, asmentioned in:
https://reactjs.org/blog/2018/06/07/you-probably-dont-need-derived-state.html#what-about-memoization
I wasn't sure quite how to avoid derived state in the
object
knob, so instead I followed the same approach as #3829 and polyfilled it.How to test
The only thing I can think of is to test with a version of react prior to the introduction of
getDerivedStateFromProps
. I'm unfamiliar with your testing setup though, so I don't know how to accomplish this in an automated method. Do you already have any smoke tests for older react versions? If so, perhaps it's just a matter of a simple UI test of these components to ensure they don't go up in flames?Is this testable with Jest or Chromatic screenshots? I don't know. :(
Does this need a new example in the kitchen sink apps? No
Does this need an update to the documentation? No