albiremo
albiremo

Reputation: 207

Reactjs handleclick binding in a nested map not working

I am writing a simple blog component in React. The component get the post from a second file and renders the content and the hashtags with map (in particular two nested map). I was trying to create a part in which the hashtag are highlighted when clicked, and hence I was following the snippet of the answer to this question. The fact is that it is not working and in particular what it is not working is the binding through bind (checked with console.log output)

class Blog extends React.Component {
state= {
    open: {}
}

handleClick = (k) => {
    let linkOpenState = true;
    if (this.state.open.hasOwnProperty(k)) {
        linkOpenState = !this.state.open[k];
    }
    this.setState({ open: { [k]: linkOpenState } })
}

render(){
return(
posts.map(i=>(
  <div class="box">
    <article class="media">
      <div class="media-content">
        <div class="content">
        <h1 class="title">{i.title}</h1>
          <p>
            {i.content}
          </p>
        </div>
        <div class="tags">
         {i.hash.map(k=>(<span id={k} onClick={this.handleClick.bind(this,k)} class={this.state.open[k]? "tag is-primary" : "tag"} >{k}</span>))}
        </div>
      </div>
    </article>
  </div>))
)
}
}
export default Blog

Anyone has an idea of what is wrong there? Is it the nested map a problem for the bind?

Upvotes: 3

Views: 146

Answers (2)

NeERAJ TK
NeERAJ TK

Reputation: 2695

React expects a single element as a return. You can solve this by wrapping the return in a fragment as <React.Fragment> or <>. Also, you don't need to bind an arrow function(handleClick when mapping i.hash).

render(){
 return(
  <>
  posts.map(i=>(
  <div class="box">
    <article class="media">
      <div class="media-content">
        <div class="content">
        <h1 class="title">{i.title}</h1>
          <p>
            {i.content}
          </p>
        </div>
        <div class="tags">
          {i.hash.map(k=>(<span key={k} id={k} onClick={() => this.handleClick(k)} class={this.state.open[k]? "tag is-primary" : "tag"} >{k}</span>))}
        </div>
      </div>
    </article>
  </div>))
</>)}}

Upvotes: 1

Rabi jha
Rabi jha

Reputation: 328

You don't need to bind the arrow function. Also, you need to pass unique key to elements when used inside map, you can use index as a key but if you are mutating the array then use some id or hash or anything which will be unique.

class Blog extends React.Component {
state= {
    open: {}
}

handleClick = (k) => {
    let linkOpenState = false;
    if (this.state.open.hasOwnProperty(k)) {
        linkOpenState = this.state.open[k];
    }
    this.setState({ open: { [k]: linkOpenState } })
}

render(){
return(
posts.map((i, index)=>(
  <div class="box" key={i.id || index}>
    <article class="media">
      <div class="media-content">
        <div class="content">
        <h1 class="title">{i.title}</h1>
          <p>
            {i.content}
          </p>
        </div>
        <div class="tags">
         {i.hash.map(k=>(<span key={k} id={k} onClick={() => this.handleClick(k)} class={this.state.open[k]? "tag is-primary" : "tag"} >{k}</span>))}
        </div>
      </div>
    </article>
  </div>))
)
}
}
export default Blog

Upvotes: 1

Related Questions