Defining and exporting HOC in React

2020-06-04 09:13发布

问题:

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?

回答1:

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



回答2:

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



回答3:

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} />