Tenten Ponce
Tenten Ponce

Reputation: 2506

Passing function from props to outside of the component (High Order Component)

I'm trying to pass the function from high order component outside the class because I need to call it but it is also needed to be pass back. Hard to explain, here's the code:

Wrapped Component:

class foo extends React.Component {
    ....
}

foo.list = [
   {
      name: "Home",
      action: this.props.funcFromHoc //this.props.from foo class, how can i access this because it is outside the component?
   }
]

export default bar(foo);

High Order Component:

export default function bar(WrappedComponent) {

   funcFromHoc() {
      alert("Hello from HOC function!");
   }

   render() {
      return (
         <WrappedComponent 
            { ...this.props }
            funcFromHoc={ this.funcFromHoc }
      );
   }
}

What I'm actually doing: I have a base screen (HOC) with a 2 drawers, that has some functions that controls their behavior. I need this 2 drawers on many screens that I'll make, I don't want to put the configuration of the drawer for every screens, that's why I create a HOC for this. My problem is, the list on the drawer on HOC is dynamic on each screens, and they have specific function that I set on each screens, how can I pass a function from the screen component to HOC?

Am I missing something or this? Am I doing it wrong? Did I missed some of the proper usage of High Order Components? Or what method should I use for this? Any hint or help will be very much appreciated. Thank you.

Upvotes: 0

Views: 1095

Answers (2)

Tenten Ponce
Tenten Ponce

Reputation: 2506

I've found a solution, it solves my problem using Inheritance Inversion.

class foo extends React.Component {
   list() {
     return [
        {
           name: "Home",
           action: this.funcFromHoc //successfully accessed it here!
        }
     ];
   }
}

export default bar(foo);

(High Order Component):

export default function bar(WrappedComponent) {
   return class Bar extends WrappedComponent {

      funcFromHoc() {
         alert("Hello from HOC function!");
      }

      render() {
         return (
            //call super.list() here to populate drawer list
            {super.render()}
         );
      }
   }
}

Upvotes: 1

brub
brub

Reputation: 1153

It sounds like you want to be able to pass additional parameters to the HOC. You could pass a mapping function when you call the HOC, like the color variable below. Note the HOC is defined slightly differently as well in order to take additional arguments.

edit: nevermind, you won't have access to funcFromFoo unless it is a prop of foo (i.e. defined in mapDispatchToProps). heh- i tried. may need to rethink the design so this isn't a requirement.

function doSomethingWithList(props) {
  const { actionName, funcFromHOC, funcFromFooProps } = props;
  if (actionName === 'Home') {
    funcFromHOC();
  } else {
    funcFromFooProps();
  }
}; 

const makeToggleable = (WrappedComponent, color) => {
  return class ToggleableComponent extends React.Component {
    constructor(props) {
      super(props);

      this.state = { toggled: false };
      this.toggleColor = this.toggleColor.bind(this);
    }

    toggleColor() {
      this.setState({ toggled: !this.state.toggled });
    }

    render() {
      const fontColor = this.state.toggled? color: 'black';
      return (
        <WrappedComponent { ...this.props }
          style={{color: fontColor}}
          onClick={this.toggleColor} />
      );
    }
  }
}

export default makeToggleable(BaseComponent, 'red');

const listItems = [ 'Home', 'Other' ]; 

export default bar(foo, listItems, doSomethingWithList);

pass listItems and doSomethingWithList for OP's question, modify HOC to call doSomethingWithList with props

example code from https://spin.atomicobject.com/2017/03/02/higher-order-components-in-react/

Upvotes: 0

Related Questions