Reputation: 115
I am trying to iterate over an Immutable.js map, to render a component, however although this is rendering, it is also rendering the key to the page. I am not sure why.
render() {
const myMap = new Map({foo: '', bar: 'http://google.com/'})
const {showFoo, titleAndUrl} = this.props
return (
<ul style={[
styles.container,
showFoo && styles.container.inline,
]}>
{myMap.map((title, url) => this.renderTab(url, title))}
</ul>
)
}
renderTab(title, url) {
const {showFoo, isFoo} = this.props
return (
<li key="sb" style={[
styles.listItem,
showFoo && styles.listItem.inline,
]}>
<a
href={url}
key={title}
style={[
styles.link,
styles.activeLink,
showFoo && styles.link.inline,
]}
className={isFoo ? "style" : ''}>
{title}
</a>
</li>
)
}
}
The two names and urls are rendered correctly, however duplicate keys are rendered i.e. foo is rendered twice and so is bar, but one of the foo and bar keys has no styles, which suggests it's being rendered outside of this.renderTab
Rendered HTML:
<ul data-radium="true"
style="display: flex; align-items: center; padding: 0px; margin: 0px; list-style: none; width: 100%; border-top: 1px solid rgb(221, 221, 221); height: 48px;">
foo
<li data-radium="true" style="display: flex; width: 50%; height: 47px; cursor: default;"><a href=""
class=""
data-radium="true"
style="display: flex; justify-content: center; align-items: center; width: 100%; text-decoration: none; font-weight: 500; font-size: 16px; color: rgb(0, 31, 91); transition: color 0.1s linear;">foo</a>
</li>
bar
<li data-radium="true" style="display: flex; width: 50%; height: 47px; cursor: default;"><a
href="http://google.com" class="" data-radium="true"
style="display: flex; justify-content: center; align-items: center; width: 100%; text-decoration: none; font-weight: 500; font-size: 16px; color: rgb(0, 31, 91); transition: color 0.1s linear;">bar</a>
</li>
</ul>
Upvotes: 1
Views: 969
Reputation: 20236
You have mixed up the order of your arguments, assigning title
to url
and vice versa.
Also, the arguments passed to the callback function for Immutable.Map.map are (1) value, (2) key, so the fist argument is your URL and the second is your title.
Change the line with the call to map
like so:
{myMap.map((url, title) => this.renderTab(title, url))}
Another problem is that the list item elements you are rendering all have the same key “sb”, only the key of the “a” elements change, but that is not even needed.
Change the JSX returned by renderTab
to this:
<li key={title} style={[
styles.listItem,
showFoo && styles.listItem.inline,
]}>
<a
href={url}
style={[
styles.link,
styles.activeLink,
showFoo && styles.link.inline,
]}
className={isFoo ? "style" : ''}>
{title}
</a>
</li>
Finally, the main mistake is that you expect Immutable.Map.map
to return an array, but it doesn't, it returns another immutable map, so you have to convert the value returned by the map function to an array using valueSeq and toArray.
So your map statement should actually look like this:
{myMap.map((url, title) => this.renderTab(title, url)).valueSeq().toArray()}
→ see related post on Stack Overflow
Upvotes: 2