1

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;

3 Answers 3

1

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...

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks your solution works! I had trouble with the way my tags were aligned in the return statement. And your last solution is more concise too, thanks again!
@Shaoz like other people have said, it's not very performant. It's fine for small amounts of data, but if your message list or members list grows, it'll get real slow real fast. find internally uses a "sequential scan" (can't for the life of me remember the non-RDB term for that this morning), iterating over the array until the condition returns true - so it's more concise, but it's no more efficient.
1

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>
    )
}

Comments

0

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

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.