Search code examples
javascriptreactjsmeteorecmascript-6flow-router

Passing a function down multiple children components in React using ES6


I have a LayoutComponent, PageComponent, and SingleComponent.

When my user clicks a button, I want to display a message to the user on a NewPageComponent that my application routes to using Meteor's FlowRouter.

To do this, I am storing the message in LayoutComponent's state, and then passing this message and a handlerMethod down as props to the SingleComponent via PageComponent, which is a stateless functional component.

I am not having any luck passing the handlerMethod down properly to the SingleComponent in order to set the message state on LayoutComponent.

I know this is a simple syntax issue, but could someone help me find my error?

LayoutComponent:

export default class LayoutComponent extends Component {
  constructor() {
    super();

    this.state = {
      message: null
    };

    this.handlerMethod = this.handlerMethod.bind(this);
  }

  handlerMethod(message) {
    this.setState({ message: message });
  }

  render() {
    // the PageComponent is actually passed via FlowRouter in this.props.content, so it needs to be cloned to add props
    let contentWithProps = React.cloneElement(this.props.content, { message: this.state.message, handlerMethod: ((message) => this.handlerMethod) });
     return (
       <div>{contentWithProps}</div>
     );
  }
}

PageComponent:

const PageComponent = ({ message, handlerMethod }) => {
  return (
    <div>
      <SingleComponent message={message} handlerMethod={(message) => handlerMethod} />
    </ div>
  );
}

Component:

export default class SingleComponent extends Component {
  constructor() {
    super();

    this.state = {
    };
    this.handleButtonClick = this.handleButtonClick.bind(this);
  }

  handleButtonClick(event) {
    event.preventDefault();
    // do some more stuff...
    this.props.handlerMethod("You pressed the button!");
    FlowRouter.go("newPage");
  }

  render() {
    <div>
      <button onClick={this.handleButtonClick}>button</button>
    </div>
  }
}

Solution

  • You aren't actually calling your handlerMethod in the code you posted. So this:

    handlerMethod: ((message) => this.handlerMethod)
    

    Should be either:

    handlerMethod: ((message) => this.handlerMethod(message))
    

    Or more simply:

    handlerMethod: this.handlerMethod