Reputation: 10653
I have a props which includes users array and messages array. Each user and message is related through a corresponding ID.
I want to match these IDs so I can render messages with the user who posted it.
The issue is nothing is rendering on screen but in the console.log()
, I can see the results. Please, can someone shed some light into this.
Also I'm not sure if I'm doing this the right way, so if you can show me a better way, I'll be glad.
Thanks
React:
import React, { Component } from 'react';
class Messages extends Component {
constructor(props) {
super(props);
}
render() {
let self = this;
return (
<ul>
{
this.props.messages.map((message, msg_key) => {
self.props.members.forEach((member) => {
if (member.id === message.userId) {
console.log('inside foreach message.userId', message.userId); // this shows in console.
console.log('inside foreach member.id', member.id); // this shows in console.
return <p>member.id</p> // nothing shows on screen.
}
})
})
}
</ul>
);
}
}
export default Messages;
Upvotes: 1
Views: 147
Reputation: 25862
you should redefine your data structure. What you currently have is not going to be performant.
instead of an array of members.. you should have an object key'd by the member id. This is so you can lookup a member by their id. Anytime you have information that is going to be used for other fields of data you should have a key value storage setup key'd by the unique identifier that maps to the other pieces of information. Heres an example
members: {
1: { id: 1, name: 'foo'},
2: { id: 2, name: 'bar'}
}
when you define a data structure like this you can easily look up members for messages.
render (){
const elems = [];
this.props.messages.forEach((message, msg_key) => {
const member = this.props.members[message.userId];
if (member) {
elems.push(
<li key={msg_key}>
<p>{message.title}</p> /* or whatever you want from the message */
<p>{member.id}</p>
</li>
);
}
})
return (
<ul>
{elems}
</ul>
)
}
Upvotes: 1
Reputation: 9458
forEach
has no side-effect. Use map
return (
<ul>
{
this.props.messages.map((message, msg_key) => {
return self.props.members.map((member) => { // <-- this line
if (member.id === message.userId) {
console.log('inside foreach message.userId', message.userId); // this shows in console.
console.log('inside foreach member.id', member.id); // this shows in console.
return <p>member.id</p> // nothing shows on screen.
}
})
})
}
</ul>
)
what I mean by "side-effect" is that it neither returns anything nor modifies the original array - map
returns a modified array.
remember to supply a key
prop when returning an array.
edit
Ah, actually ^ doesn't do what you want.
Array
has a nice method to accomplish what you're attempting, find
return (
<ul>
{
this.props.messages.map((message, msg_key) => {
const member = self.props.members.find((member) => member.id === message.userId)
return <p>{member.id}</p>
})
}
</ul>
)
edit #2
well... it actually does work, but it's not pretty. React won't render null
in arrays, so it'll skip the ones where the condition wasn't true...
Upvotes: 1
Reputation: 157
I think you might messed up some of the attributes inside the array by having 2 loops at 1 time (map, and forEach).
Try have a helper function to map through (instead of forEach) the member.id attributes. So just call {this.renderMemberList} inside the render().
Do you have a JSFiddle set up? it would be easier
Upvotes: 0