0

I have a Context Consumer which works like this:

<ToastConsumer>
          {({ openToast }) => (
            <button onClick={() => openToast('You clicked Button A!')}>
              Button A
            </button>
          )}
        </ToastConsumer>

But I want to add some extra logic on the click handler and move the openToast Consumer function like this:

 upVote = () => {
    if (!this.state.hasVoted) {
      this.setState({
        hasVoted: true,
        rating: this.state.rating + 1,
      });

      this.vote(this.state.rating + 1);
    }

    this.openToast // not working???
  };


      <ToastConsumer>
        {({ openToast }) => (
          <div className="vote-button">
            <span
              className="vote-up vote-action cursor-pointer"
              onClick={this.upVote}
            >
              👍 +1...

All of the examples provided for the Context API seem to be a simple click handler and I cant workout how to acheive a more complex example like this one.

2 Answers 2

2

One way to achieve this is to pass your openToast function into your new handler. You can do this either by wrapping the onClick in a function, or by currying your upVote function.

Examples:

Wrapping in a function:

upVote = (openToast) => {

onClick={() => this.upVote(openToast)}

Currying upVote:

upVote = (openToast) => () => {
onClick={this.upVote(openToast)}
Sign up to request clarification or add additional context in comments.

Comments

1

openToast needs to be provided to upVote as an argument (as another answer already mentions), upVote becomes higher-order function:

upVote = openToast => () => {
  // ...
  openToast();
}

And used like:

<span onClick={this.upVote(openToast)}>

A way to avoid this complexity with context consumers is to make a context available in class instance. This can be done with contextType:

static contextType = ToastContext;

upVote = openToast => () => {
  // ...
  this.context.openToast();
}

A downside is that this restricts a component to be used with one context.

Or a context can be provided to a component with a HOC:

const withToast = Comp => props => (
    <ToastConsumer>
      {({ openToast }) => <Comp openToast={openToast} ...props/>}
    </ToastConsumer>
);

Then a component that was connected to a context with withToast(MyComponent) receives openToast as a prop:

upVote = openToast => () => {
  // ...
  this.props.openToast();
}

1 Comment

Thank you for the very comprehensive answer

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.