React - change this.state onClick rendered with array.map()

so based off your code you could do it a couple of ways.

onClick=(event) => this.gotoCoffee(event.target.value)

This looks like the approach you want.

onClick=() => this.gotoCoffee(c)

c would be related to your item in the array.


You can pass index of element to gotoCoffee with closure in render. Then in gotoCoffee, just access that element as this.state.coffees[index].

gotoCoffee = (index) => {
    this.setState({isLoading:true, select: this.state.coffees[index]})
    setTimeout(()=>{
      this.setState({isLoading:false,redirect:true})
    },5000)
  }

  render(){
    const data = this.state.coffees;

    return (
      <div>
        <h1 className="title is-1"><font color="#C86428">Menu</font></h1>
        <hr/><br/>
        {data.map((c, index) => 
          <span key={c}>
            <div>
               {this.state.isLoading && <Brewing />}
               {this.renderCoffee()}
              <div onClick={() => this.gotoCoffee(index)} 
                  <strong><font color="#C86428">{c}</font></strong></div>
            </div>
          </span>)
        }
      </div>
    );
  }
}

All the answers look alright and working for you and it's obvious you made a mistake by not passing the correct value in click handler. But since you're new in this era I thought it's better to change your implementation this way:

  • It's not necessary use constructor at all and you can declare a state property with initial values:

    class Menus extends Component{
        state= {
            /* state properties */
        };
    }
    
  • When you declare functions in render method it always creates a new one each rendering which has some cost and is not optimized. It's better if you use currying:

    handleClick = selected => () => { /* handle click */ }
    render () {
        // ...
        coffees.map( coffee =>
            // ...
             <div onClick={ this.handleClick(coffee) }>
            // ...
    }
    
  • You can redirect with history.replace since you wrapped your component with withRouterand that's helpful here cause you redirecting on click and get rid of renderCoffee method:

    handleClick = selected => () => 
        this.setState(
            { isLoading: true},
            () => setTimeout(
                () => {
                    const { history } = this.props;
                    this.setState({ isLoading: false });
                    history.replace(`/${coffee}`);
                }
                , 5000)
        );
    

Since Redirect replaces route and I think you want normal page change not replacing I suggest using history.push instead.