Rafael Marques
Rafael Marques

Reputation: 1445

React - onClick(item) of item in list using for loop

I am making a react list, whose items should trigger an action to update state. Both the triggering and the state update occur, however, the onClick method is calling the action with the same argument every time. This should not occur. The argument passed to the action must depend on the item of the list clicked.

I can not seam to find the bug that is causing this error.

This is my dropdown class, where the list is rendered.

class DropDownMenu extends React.Component {
  constructor(props){
    super(props)
  }
  render(){
    let content = []
    var categories = this.props.categories
    for (var i=0; i < categories.length; i++) {
      var catName = categories[i]
      var line = (
        <li
          key ={i}
          onClick = {() => {this.props.onClick(catName)}}
        >
        <p>{catName}</p>
        </li>
      )
      content.push(line)
    }
    return (
      <div>
        <Dropdown ref="dropdown">
          <DropdownTrigger>Categories</DropdownTrigger>
          <DropdownContent>
            <ul>
              { content }
            </ul>
          </DropdownContent>
        </Dropdown>
      </div>
    )
  }
}

This is the container that manages the state and calls the above class

class MenuContainer extends React.Component {
  constructor(props) {
    super(props)
  }

  render(){
    return (
      <div>
        <div>
          <a onClick = {() => {this.props.changeView("main")}}>back</a>
          <a onClick = {() => {this.props.changeView("shoppingCart ")}}>my cart</a>
        </div>
        <div>
          <DropDownMenu
            categories = {this.props.categories}
            onClick = {(catName) => {this.props.selectCategory(catName)}}
          />
          <ItemList
            items = {this.props.items}
          />
        </div>
      </div>
    )
  }
}

const mapStateToProps = (state) => {
  return {
    categories: getCategories(state),
    items: getItems(state)
  }
}

const mapDispathToProps = (dispatch) => {
  return {
    changeView: (view) => {
      dispatch(setView(view))
    },
    selectCategory: (catName) => {
      dispatch(setCategory(catName))
    }
  }
}

export default connect(mapStateToProps, mapDispathToProps)(MenuContainer)

I reducer the error to the line:

   for (var i=0; i < categories.length; i++) {
      var catName = categories[i]
      var line = (
        <li
          key ={i}
          onClick = {() => {this.props.onClick(catName)}}
        >
        <p>{catName}</p>

I replaced this.props.onClick with console log of the catName, and it always logs the same, althoug it correctly shows the items in the

tag.

Upvotes: 0

Views: 6420

Answers (1)

Prakash Sharma
Prakash Sharma

Reputation: 16472

Your for loop does not form a closure. Better use a map function like this

let content = categories.map((catName, i) => {
      return (
        <li
          key ={i}
          onClick = {() => {this.props.onClick(catName)}}
        >
        <p>{catName}</p>
        </li>
      )
    });

Upvotes: 7

Related Questions