hoist-non-react-methods
Copies non-react specific methods from a child component to a parent component
Inspired by @mridgway's hoist-non-react-statics
When wrapping a component (see Higher-Order Components methods that are defined in the child component aren't accessible anymore. This module makes those methods available on the wrapper component's prototype.
Installation
npm install hoist-non-react-methods --save
When is it needed?
Components can have public methods that are accessible through their instance under parent's refs
.
class Composer extends React.Component {
render() {
return <input type="text" ref="input" />
}
focus() {
return this.input.focus()
}
}
class Root extends React.Component {
render() {
<div>
<button onClick={e => this.refs.composer.focus()}></button>
<Composer ref="composer" />
</div>
}
}
Assuming you have a component which is decorated, the method focus
will be lost, because the ref
will point the decorator component.
@someDecorator()
class Composer extends React.Component {
render() {
return <input type="text" ref="input" />
}
focus() {
return this.input.focus()
}
}
function someDecorator() {
return function (WrappedComponent) {
class Wrapper extends Component {
static displayName = `Wrapper(${WrappedComponent.displayName})`
componentWillMount() {
}
render() {
return <WrappedComponent ref="wrappedComponent" />
}
}
return Wrapper
}
}
class Root extends React.Component {
render() {
<div>
<button onClick={e => this.refs.composer.focus()}></button>
<Composer ref="composer" />
</div>
}
}
This package provides a function that copies all the methods (prototype and static) from the wrapped component to the wrapper, but keeps all react specific methods (e.g. componentDidMount
etc.) untouched.
@someDecorator()
class Composer extends React.Component {
componentWillMount() {
}
render() {
return <input type="text" ref="input" />
}
static someStaticMethod() {
}
focus() {
return this.input.focus()
}
}
function someDecorator() {
return function (WrappedComponent) {
class Wrapper extends Component {
static displayName = `Wrapper(${WrappedComponent.displayName})`
componentWillMount() {
}
render() {
return <WrappedComponent ref="wrappedComponent" />
}
}
return hoistNonReactMethods(Wrapper, WrappedComponent, c => c.refs.wrappedComponent)
}
}
class Root extends React.Component {
render() {
<div>
<button onClick={e => this.refs.composer.focus()}></button>
<Composer ref="composer" />
</div>
}
}
API
hoistNonReactMethods(
Wrapper: ReactComponent,
WrappedComponent: ReactComponent,
delegateTo: function(ReactComponent wrapperComponentInstance):ReactComponent childComponentInstance
)
The third parameter is a function that gets the instance of the wrapper component and returns the instance of the wrapped component (e.g. (wrapper) => wrapper.refs.child
)
Test
npm install
npm test
License
MIT