Reputation: 23
So basically I am trying to build a messages page where users can see all of their active threads with other users. One of the things I'm trying to accomplish is displaying some basic info about each thread in a list, before they can click on it and go into the details and the actual thread itself. The problem I'm having is when I'm trying to display the name of the user that they are chatting with. In my component for this page, I first fetch all of threads like so: (Note that I'm using redux and this.props
is dispatched to the proper fetch calls)
componentDidMount(){
this.props.getMessageThreads()
.then(response => {
this.setState({threads: response})
})
}
Each thread has a field user1
and user2
which are the IDs of the two users chatting with each other. In my render, I am simply trying to display a table with all of the names of the other user that the current one is chatting with. I check which ID matches with the current user, and save the one that isn't the current user in the collaboratorID
variable. The problem arises when I have to make another fetch call with this collaboratorID
, and for some reason it doesn't want to display it properly. I've debugged using console.log()
and pinpointed that all of the fetch calls including the one in getName(id)
are returning the proper responses.
In my render()
:
{this.state.threads.map((thread, index) => {
let collaboratorID;
thread.user1 === this.props.user.id ? collaboratorID = thread.user2 : collaboratorID = thread.user1
return (
<TableRow key={index}>
<TableCell component="th" scope="row">
{this.getName(collaboratorID)}
</TableCell>
</TableRow>
)
})}
My getName(id)
function:
getName(id){
this.props.loadAnotherUser(id)
.then(response => {
return response.profile.display_name
})
}
Right now it isn't displaying anything at all and the table is blank. Before when I was messing around with it I was able to get it to display the names by having a names state array and doing this.setState({ names: [...this.state.names, response.profile.display_name] })
inside of a for loop, but the names would always display out of order and mixed up. This way of doing it also seems redundant and unnecessary but I could be wrong. Anyways, I would appreciate any input on this one. Thanks in advance!
Upvotes: 2
Views: 658
Reputation: 1116
react is just re-render only when state was updated, I think you can try it like this:
async componentDidMount() {
// first, get threads data.
const threads = await this.props.getMessageThreads();
// then we need to get displayName for every single thread
const threadsWithDisplayName = await Promise.all(
threads.map((t) =>
this.props
.loadAnotherUser(t.user1 === this.props.user.id ? t.user2 : t.user1)
.then((response) => ({
...t,
displayName: response.profile.display_name,
}))
)
);
// save the result into state
this.setState({ threads: threadsWithDisplayName });
return Promise.resolve();
}
and then just access displayName
in your render.
{this.state.threads.map((thread, index) => (
<TableRow key={index}>
<TableCell component="th" scope="row">
{thread.displayName}
</TableCell>
</TableRow>
)}
I have not actually tested the above code, it may not be 100% correct, but the idea is probably like this.
Upvotes: 2