I've been research Higher Order Components in react. My requirement is that I have a set components which I need to extend to give them more functionality without rewriting the entire component. In this case, I found out the concept HOC in react where one could extend the component using a pure function. My question is, can I export the extended component as a normal component. For an example
Component which needs to be extended
class foo extends React.Component {
render(){
//something
}
}
export default foo;
HOC component
function bar(foo) {
render() {
return <foo {...this.props} {...this.state} />;
}
}
export default bar;
Am I able to use the component that way? or am I doing it wrong?
A HOC would take a component, add some more functionality and return a new component and not just return the component instance,
What you would do is
function bar(Foo) {
return class NewComponent extend React.Component {
//some added functionalities here
render() {
return <Foo {...this.props} {...otherAttributes} />
}
}
}
export default bar;
Now when you want to add some functionality to a component you would create a instance of the component like
const NewFoo = bar(Foo);
which you could now use like
return (
<NewFoo {...somePropsHere} />
)
Additionally you could allow the HOC to take a default component and export that as a default component and use it elsewhere like
function bar(Foo = MyComponent) {
and then create an export like
const wrapMyComponent = Foo();
export { wrapMyComponent as MyComponent };
A typical use-case of an HOC could be a HandleClickOutside
functionality whereby you would pass a component that needs to take an action based on handleClickOutside
functionality
Another way could be like this:
Make a Foo Component
class Foo extends React.Component {
render() {
return ( < h1 > hello I am in Foo < /h1>)
}
}
Make a HOC component.
class Main extends React.Component {
constructor(props) {
super(props);
}
render() {
const {
component, props
} = this.props;
//extract the dynamic component passed via props.
var Component = component;
return ( < div >
< h1 > I am in main < /h1>
< Component {...props} > < /Component>
</div > );
}
}
ReactDOM.render( < Main component = {
Foo
} > < /Main>,
document.getElementById('example')
);
Working code here
Yes you can
const bar = (Foo) => {
return class MyComponent extend Component {
render() {
return <Foo {...this.props} />
}
}
}
//Our Foo Component Code Here
export default bar(Foo)
But again it depends on the functionality. Eg: suppose you're using react router and want to check if user is present before rendering the component don't pass the HOC. eg:
<Route path="/baz" component={auth(Foo)} />
Instead use an new component.
Note: NewComponent is connected to redux and user (state) is passed as props
class NewRoute extends Component{
render(){
const {component:Component, ...otherProps} = this.props;
return(
<Route render={props => (
this.props.user? (
<Component {...otherProps} />
):(
<Redirect to="/" />
)
)}
/>
);
}
}
Then on the routes
<NewRoute path='/foo' component={Foo} />