-
-
Notifications
You must be signed in to change notification settings - Fork 10.6k
Removal of React 16.3 unsafe lifecycles #6256
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
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -33,10 +33,6 @@ class Router extends React.Component { | |
}; | ||
} | ||
|
||
state = { | ||
match: this.computeMatch(this.props.history.location.pathname) | ||
}; | ||
|
||
computeMatch(pathname) { | ||
return { | ||
path: "/", | ||
|
@@ -46,8 +42,9 @@ class Router extends React.Component { | |
}; | ||
} | ||
|
||
componentWillMount() { | ||
const { children, history } = this.props; | ||
constructor(props) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The subscription can't go in the constructor. If the component is removed from the tree before rendering (which may happen in async rendering), we'll leak a subscription to the history instance. The subscription needs to be put in a componentDidMount. |
||
super(props); | ||
const { children, history } = props; | ||
|
||
invariant( | ||
children == null || React.Children.count(children) === 1, | ||
|
@@ -62,13 +59,18 @@ class Router extends React.Component { | |
match: this.computeMatch(history.location.pathname) | ||
}); | ||
}); | ||
|
||
this.state = { | ||
match: this.computeMatch(this.props.history.location.pathname) | ||
}; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This change isn't needed. The class field above transpiles/desugars into this exact same form. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. makes sense! |
||
} | ||
|
||
componentWillReceiveProps(nextProps) { | ||
shouldComponentUpdate(nextProps) { | ||
warning( | ||
this.props.history === nextProps.history, | ||
"You cannot change <Router history>" | ||
); | ||
return true; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this will have an unintended negative perf side effect. While not the worst thing in the world (we don't do a whole lot in the render), technically this will cause this component to render on every update, even if it's unneeded. While the error message will need to change (we're not preventing the change, only warning that it will have no effect), I believe this actually belongs in cDU: https://reactjs.org/blog/2018/03/27/update-on-async-rendering.html#side-effects-on-props-change There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @timdorr maybe we could use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think that's exactly what is suggested (to use static getDerivedStateFromProps(nextProps) {
warning(
this.props.history === nextProps.history,
"You cannot change <Router history>"
);
return null;
} There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You can't use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @timdorr @grzegorzjudas following what is proposed here (https://github.com/reactjs/rfcs/blob/master/text/0006-static-lifecycle-methods.md#state-derived-from-propsstate), I think we should mirror There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. gDSFP is intended to be a pure function, so I don't think that would work. cDU might be a better option. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @timdorr Ah, right, my bad. |
||
} | ||
|
||
componentWillUnmount() { | ||
|
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.
Because we're mainly doing a subscription here, we should be following the React async guidelines and move the listener to a cDM: https://reactjs.org/blog/2018/03/27/update-on-async-rendering.html#adding-event-listeners-or-subscriptions
I'm not sure where the best place for the invariant check would be. Possibly just the render method.
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.
@timdorr I think that invariant could stay in
constructor
and just move the subscription for cDM, since, IMO theinvariant
needs to be the first thing to do here.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.
Technically, you could change the children of
<Router />
when component is already rendered, causing it to re-render. If it's in constructor, you won't get the message then. Possiblystatic getDerivedStateFromProps
again? As it's called every time component receives props.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.
@grzegorzjudas That's a good point. I think we could follow with
getDerivedStateFromProps
forinvariant
, since it's called inMounting
andUpdating
phases.