-
-
Notifications
You must be signed in to change notification settings - Fork 10.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
Add withRouter HoC #3352
Add withRouter HoC #3352
Conversation
Huh ... I was thinking function withRouter(Component) {
return React.createClass({
contextTypes: { router: routerShape },
render() {
return <Component {...this.props} router={this.context.router}/>
}
})
} That doesn't copy over the static methods, but ... I dunno ... does redux copy over the statics? |
Yes: https://github.com/reactjs/react-redux/blob/master/src/components/connect.js#L365 Also, that won't provide it on |
Yeah, I want |
How about decoration over composition? function withRouter(Component) {
if (! Component.contextTypes) {Component.contextTypes = {};}
Component.contextTypes.router = Router.PropTypes.router;
} |
@Download I didn't want to create a side effect. |
You want composition because the idea is to make consumers not care about context. I'd definitely set |
@ryanflorence But why? @timdorr What is the problem with a side effect? We are talking React components right? Mostly we just create them at app start and that's it. What issues do you see? |
Ugh, I hear ya, that's just a lot more busywork. |
My reasoning is that, given React's user base, |
Switched it up to |
WithRouter.displayName = `withRouter(${getDisplayName(WrappedComponent)})` | ||
WithRouter.WrappedComponent = WrappedComponent | ||
|
||
return hoistStatics(WithRouter, WrappedComponent) |
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.
Oh, wow, Redux does this? I feel like most wrappers these days don't. The Relay container doesn't, for example.
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.
Yeah, it's just to avoid unexpected surprises from adding static methods. See reduxjs/react-redux#270 (comment)
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.
Wow, @gaearon is unusually charitable to his users. 😛
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.
Well, it’s React Router that used to expect willTransitionTo
on statics 😄 .
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.
Trailblazers gonna trail blaze.
LGTM other than the test nit, BTW. I assume we'll want to update docs on another PR, right? Otherwise it's going to get hairy. |
I was going to do the doc changes here too. All of that should go together. |
+1 to docs change on this commit, will be nice to see it together, sorry I know it's a pain, if you want me to do it, I can do it on my flight to Boston next week :) |
f24f046
to
ced9448
Compare
Added docs and updated the examples. Also forgot the export. Should be good to go. |
@@ -162,6 +163,9 @@ Given a route like `<Route path="/users/:userId" />`: | |||
### `<IndexLink>` | |||
An `<IndexLink>` is like a [`<Link>`](#link), except it is only active when the current route is exactly the linked route. It is equivalent to `<Link>` with the `onlyActiveOnIndex` prop set. | |||
|
|||
### `withRouter(component)` | |||
A HoC (higher-order component) that wraps another component to provide `this.props.router`. Pass in your component and it will return the wrapped 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.
Mention that it can also be used as a decorator on classes
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.
Oops, that should have been a question – I mean, "do we want to mention that?"
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 was thinking about that, but decorators aren't in babel 6 unless you include the non-default babel-plugin-transform-decorators-legacy
. Given the state of flux surrounding them, I'm hesitant to bring attention to them right now.
You don't need the explicit |
I was getting unnamed components. Does that apply to Babel 5? (which we're still on!) |
I guess it must be a new Babel 6 feature. Bleh. |
I'm inclined to say we omit for the sake of terseness anyway. |
Maybe we should update to Babel 6... 👹 |
Any reason we don't? |
I remember there being some issues with the examples in Babel 6. I think we figured all of that out, so I'm not sure why not. I can try out a PR later on to see how much work is involved and to centralize discussion. |
I just started on Babel 6. We need a custom transform to preserve module exports, and it's a bit of work to avoid breaking the ES build. |
Redux does that via an env: https://github.com/reactjs/redux/blob/master/.babelrc |
Yup, I know. Just need to tweak a bit to preserve some of our functionality. |
I see the automatic |
Also add an export of withRouter
Yep, I'll get rid of them now. |
* Create a withRouter HoC. * withRouter passes this.props.router * Update docs, examples, and upgrade guide. Also add an export of withRouter * Doc tweaks. * Remove displayNames.
Closes #3350.
This is a little funky because we have to set a static on the composed component. I was originally just going to set
Component.contextTypes
and call it a day, but that creates a side effect. Is there any downside or error in the proposed solution?hoist-non-react-statics
is nice to keep from running into unintended surprises (especially if the component is wrapped multiple times).