0

In my React app, I have two Components, Main and Menu Component. Main Component is the parent component of Menu. Menu shows a list of items and upon clicking one of the item, it updates Main's state with the help of a function that I pass as props to Menu. Below is the code for better understanding:

class Main extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            dishes: dishes,
            selectedDish: null
        };
        this.selectDish=this.selectDish.bind(this);
      }

      selectDish(dishId){
        this.setState({ selectedDish: dishId});
      }


  render() {
    return (
      <div className="App">
        <Menu dishes={this.state.dishes} onClick={this.selectDish} />
      </div>
    );
  }
}

export default Main;

And below is the Menu Component:

class Menu extends Component {

    constructor(props){
        super(props);
        this.selectdish=this.selectdish.bind(this);
    }
    selectdish(dishId){
        return this.props.onClick(dishId);
    }

    render() {
        const menu = this.props.dishes.map((dish) => {
            return (
                <div className="col-12 col-md-5 m-1">
                <Card key={dish.id}
                  onClick={this.selectdish(dish.id)}>
                </Card>
              </div>
            );
        });

    }
}

export default Menu;

I have omissed some irrelevant parts of the code. So the workflow should be that when we click over one of dishes rendered by the Menu, that dish's id should be passed back to Main and update the state variable ```selectedDish````, as seen in the method selectDish.

But in the browser console, I get the error Cannot update during existing state transition. The weird thing is that if I don't pass any dish id and set the selectedDish to a fixed value like 1, everything works fine.

Please help me guys to identify if there is any problem in my event handler, because that is the only part that seems to contain an error.

Thank You!

2 Answers 2

1

You are not passing the onClick of the Card a function but you are already calling that function with this.selectdish(dish.id). This will initiate the flow on render, not on click.

You have three options here.

You either wrap that in an additional function like this: onClick={() => {this.selectdish(dish.id)}}>. That way, you are passing a function to the onClick, which is required, and not executing that.

Or you make selectdish return a function like this:

 selectdish(dishId){
    return () => {this.props.onClick(dishId)};
}

Or you add a name to the card and access the name of the element from the click event:

class Menu extends Component {

constructor(props){
    super(props);
    this.selectdish=this.selectdish.bind(this);
}
selectdish(event){
    return this.props.onClick(event.target.name);
}

render() {
    const menu = this.props.dishes.map((dish) => {
        return (
            <div className="col-12 col-md-5 m-1">
            <Card key={dish.id}
              name={dish.id}
              onClick={this.selectdish}> // this is now the function without calling it
            </Card>
          </div>
        );
    });

}
}

export default Menu;
Sign up to request clarification or add additional context in comments.

9 Comments

Thanks for the answer, but why you said that function will be executed during render. In plain javascript, we do it like that itself.
this.selectdish(dish.id) will execute a function right? So onClick={this.selectdish(dish.id)}> will also execute the function on render
why on render, it should be executed on click. I can't get that part.
One more thing, why we're even returning the function inside selectdish. Why can't we just caall the function?
Because whenever you write function(), you execute it. And you are doing that. YOu need to wrap that in an additional function and pass that function to the onClick to be executed on Click,
|
0

You have some problem in your code:

  1. property key must be define in root <div>
  2. render method in Menu component returns nothing

-

class Menu extends React.Component {
  constructor(props) {
    super(props);
    this.selectdish = this.selectdish.bind(this);
  }
  selectdish(dishId) {
    return this.props.onClick(dishId);
  }

  render() {
    return this.props.dishes.map(dish => {
      return (
        <div className="col-12 col-md-5 m-1" key={dish.id}>
          <div onClick={() => this.selectdish(dish.id)}>{dish.id}</div>
        </div>
      );
    });
  }
}

See my playground where I fixed this issues:

https://codesandbox.io/s/react-playground-ib6pr?file=/index.js

1 Comment

I have removed that part.

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.