-
-
Notifications
You must be signed in to change notification settings - Fork 3.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
use hoist-non-react-methods instead of hoist-non-react-statics #270
Conversation
…he wrapper component
This seems fragile and burdening to support to me, even via an external library. I'd say at this point you're better off using class MyComponent extends Component {
render() {
return (
<div>
<input ref={this.props.inputRef} />
</div>
);
}
}
class ParentComponent extends Component {
componentDidMount() {
this.input.focus();
}
render() {
return (
<MyComponent inputRef={input => this.input = input} />
)
}
} With this pattern you can also “propagate” refs just by accepting it as a prop in parent component as well: class ParentComponent extends Component {
render() {
return (
<MyComponent inputRef={this.props.inputRef} />
)
}
} Then you can perform the focus from a grandparent or further without accessing the instances. |
@gaearon: A. Can you think of a scenario where it wouldn't be desired? |
Also:
|
Static methods are hoisted because that's where people tend to put data fetching methods. There's no workaround here, and call sites are often generic doing something like "grab every In case of methods on the prototype, it's fragile (can't name methods with same names as
This is a non-goal. If you're accessing instances directly you need to be aware that there is an intermediate instance. We don't want to pretend there isn't because that will just be more confusing and magic and will force us to deal with even worse edge cases (like the naming problems I suggested above).
I don't doubt that it works. I just don't want to support it in the library in terms of docs, bugs, feature requests (“a method works but a getter doesn’t!”, “inherited methods don’t show up!”, “third party mixin has a
I hope examples above show why I don't want to support this.
No, that's more configuration to support and doesn't help with the bug / feature request burden and potential name clashes.
Use props when possible. What's wrong with passing And you don't have to pass nodes via callback props either. You can do something like class MyComponent extends Component {
componentDidMount() {
this.props.provideController({
open: () => ...,
close: () => ...,
focus: () => ...
});
}
componentWillUnmount() {
this.props.provideController(null);
}
render() {
return (
<div />
);
}
}
class ParentComponent extends Component {
componentDidMount() {
this.ctl.open();
}
render() {
return (
<MyComponent provideController={ctl => this.ctl = ctl} />
)
}
} |
All your concerns about future bugs/naming conflicts are valid.
These are exactly the methods that I would expose. A prop
A prop like |
I think your second best bet is
if this is a common pattern in your codebase. Cheers! |
👍 thanks. |
regarding #270 (comment) , how can I access/refer to the |
I changed my mind and used getWrappedInstance() instead. Thank you anyway. |
Dan @gaearon , thanks for your great input! I'm using your suggestions to implement my wizard. Basically what i'm doing is when clicking the next button in Parent component (the wizard container), I need to call the submit function of Child component (the wizard page). before I wrap my child component with connect, I was able to call wizard page's submit method by wiring up Parent -> Child thru ref, i.e
and it worked fine. I then found out that I need to wrap my child component to a connect component , and after that, I lost control to the Child component, as the activePage is now pointing to the wrapper component, which doesn't have submit method defined (only static function hoisted, not prototype) Yes, I can use getWrappedInstance() which I believe will work just fine, but I really like your idea of passing callbacks to child and let child set the value that Parent is interested in, so I decided to give it a go
and this also works fine as well. great! my question, is that when passing a callback to child, why can't we name the prop 'ref', i.e.
won't work and will cause exception at child component, saying this.props.ownProps.ref is undefined, but I have defined it and passed down to child.. don't really understand why I got that error does this mean that connect component will selectively filter out some props? |
This is because |
Great. Thanks Dan again! |
copy all wrapped component's methods (prototype and static except react methods) into the wrapper component.
so methods like
focus
on@connect() class Composer { focus() { this.refs.input.focus } }
will still be available ifComposer
isref
ed somewhere else.Original issue: #267
hoist-non-react-methods
is here: https://github.com/elado/hoist-non-react-methods