stack overflow
stack overflow

Reputation: 187

--JSX does not appear to render correctly?

I want to simply output a list of <p> tags but do no know the correct syntax.

I verified the data is correctly stored in this.props.bookmarks.bookmarks but could not figure out how to render it correctly.

I verified that there is a bookmark.title property as well.

With in the React component render() function I have as follow:

return (

// ... snip

this.props.bookmarks.bookmarks.map((bookmark) => {
  return "<p>{bookmark.title}</p>";
});

// ... snipt

)

Update:

var titles = this.props.bookmarks.bookmarks.map((bookmark) => {

  return <div className='bookmark_div' id='generated1'>
    <img className='bookmark_image' id='generated2' src='http://arcmarks.com/_images/sv_favicon.svg'/>
    <a className='bookmark_link' id='generated3'>arcmarks</a>
  </div>

});

Upvotes: 0

Views: 86

Answers (3)

agm1984
agm1984

Reputation: 17132

If you are outputting an iterable in this manner, React is going to throw a warning/error about keys, so you should attach a unique identifier also. React uses these keys to help optimize rendering as it monitors updates to the DOM.

It looks like this is embedded inside other JSX code also, so you may need to wrap it in {}

return (
  // ... snip

  {this.props.bookmarks.bookmarks.map((bookmark) => {
    return <p key={bookmark.id}>{bookmark.title}</p>;
  });}

  // ... snip
)

You could also optimize this further by destructuring the bookmarks iterable out, and utilize implicit return:

const { bookmarks } = this.props.bookmarks

return (
  // ... snip

  {bookmarks.map((bookmark) => <p key={bookmark.id}>{bookmark.title}</p>)}

  // ... snip
)

In my example, bookmark.id could be anything as long as it's unique, even bookmark.title.

To come full circle, I will just add an example that shows this inside some additional JSX/HTML so you can see it:

constructor(props) {
  super(props)
  // set initial button state to false
  this.state = {
    buttonClicked: false
  }
}

// method to handle button clicking
handleButton(e) {
  e.preventDefault()
  console.log('Radical button firing.')
  // set state to opposite of current
  this.setState({ buttonClicked: !this.state.buttonClicked })
}

render() {
  if (!this.props.bookmarks) return <div>Loading...</div>

  const { bookmarks } = this.props.bookmarks

  return (
    <div>
      <h3>Checkout my Rad Books</h3>

      {bookmarks.map((bookmark) => <p key={bookmark.id}>{bookmark.title}</p>)}

      <button onClick={(e) => this.handleButton(e)}>{(!this.state.buttonClicked) ? 'Not Clicked Yet' : 'Was Clicked'}</button>
    </div>
  )
}

When you render, you must always wrap in a parent element, in this case, we used a div. I included some wealthy data here so you can forensically analyze and test further.

We might aswell go all out here. We can pull that book list into a rendering method also:

renderBooks() {
  if (!this.props.bookmarks.bookmarks) return <div>Loading bookmarks...</div>

  const { bookmarks } = this.props.bookmarks

  return (
    <div>
      {bookmarks.map((bookmark) => <p key={bookmark.id}>{bookmark.title}</p>)}
    </div>
  )
}

render() {
  return (
    <div>
      <h3>Checkout my Rad Books</h3>

      {this.renderBooks()}

      <button onClick={(e) => this.handleButton(e)}>{(!this.state.buttonClicked) ? 'Not Clicked Yet' : 'Was Clicked'}</button>
    </div>
  )
}

Upvotes: 3

Eitan G
Eitan G

Reputation: 146

return "<p>{bookmark.title}</p>";

You seem to be trying to interpolate. You shouldn't need to interpolate it.

return <p>{bookmark.title}</p> should be good.

If you're using ES6, you can interpolate using backticks.

`My name is ${name}`

Upvotes: 0

Sumner Evans
Sumner Evans

Reputation: 9157

Assuming you have setup Babel (or some other transpiler) correctly:

return <p>{bookmark.title}</p>;

should work (no "s).

This will compile to:

React.createElement('p', null, bookmark.title);

(or something similar) in the resulting JS output.

If you want to render multiple lines of HTML, wrap your JSX in ()s:

return (
<div>
    <p>content here</p>
</div>
)

Upvotes: 1

Related Questions