3

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?

2 Answers 2

1

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>))
</>)}}
Sign up to request clarification or add additional context in comments.

6 Comments

Thank you for the tips. The value seem passed correctly to the HandleClick now but the problem seems to be now with the if in the handleclick that is never realized correctly (it seems the HasOwnProperty is not realized).
@albiremo Didn't get it. Can you comment the error?
There is no error. Simply I do not obtain the desired behaviour. Let's say that I add a bunch of console.log to check if this handleClick works ``` handleClick = (k) => { let linkOpenState = false; if (this.state.open.hasOwnProperty(k)) { linkOpenState = this.state.open[k]; } this.setState({ open: { [k]: linkOpenState } }) console.log(k) console.log(linkOpenState) console.log(this.state) } ``` I see that when I click on the hashtag, the linkOpenState return always false.
So it seems that the code never enter in the if
Sorry, I have fixed it, the problem was in the linkOpenState part. I fix it in the question. thank for your help.
|
1

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

Comments

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.