Reputation: 15
Currently, I am making a private messaging feature for a React app. I'm fairly new to React, so I'm not sure where I'm messing this up. Also, please note: For this particular project, I am unable to use jQuery/Redux/etc... just plain React.
So before I show my code, this is what results I have now:
The sent messages appear ordered properly, and the received messages are ordered properly, BUT it shows all sent messages before then showing all received messages. I would like for them all to display in the order that they were sent, regardless of which user sent it (think of how your average texting app works)
Now for my code (sorry I included a lot, I'm not sure where in the process it is messing up):
data.json
"privateMessages": [
{
"userId": 2,
"receiverId": 3,
"message": "first",
"id": 1
},
{
"userId": 3,
"receiverId": 2,
"message": "second",
"id": 2
},
{
"userId": 2,
"receiverId": 3,
"message": "third",
"id": 3
},
{
"userId": 2,
"receiverId": 3,
"message": "fourth",
"id": 4
},
{
"userId": 3,
"receiverId": 2,
"message": "fifth",
"id": 5
}
],
"users": [
{
"name": "User 1",
"id": 2
},
{
"name": "User 2",
"id": 3
}
MsgCard.js --- I suspect the problem is here but not sure.
export const MsgCard = ({message}) => {
const currentUserId = sessionStorage.getItem("nutshell_user");
if (message.sentBySelf) {
return (
<div className="sentMsg">
<h4>
<span className="nameOfSender">{message.user?.name}: </span>
{`${message.message}`}
</h4>
</div>
)
} else if (message.receiverId === parseInt(currentUserId)) {
return (
<div className="receivedMsg">
<h4>
<span className="nameOfSender">{message.user?.name}: </span>
{`${message.message}`}
</h4>
</div>
)
}
}
MsgList.js
export const MsgList = () => {
const [messages, setMessages] = useState([])
const currentUserId = sessionStorage.getItem("nutshell_user");
const getAllPMs = () => {
return fetch(`${remoteURL}/privateMessages/?_expand=user`)
.then(res=>res.json())
}
const scrollToEnd = () => {
const container = document.querySelector(".messagesContainer")
container.scrollTop = container.scrollHeight
}
const getPMs = () => {
getAllPMs().then(allPMs => {
const sentByCurrent = allPMs.filter(message => message.userId === parseInt(currentUserId))
const sentByOthers = allPMs.filter(message => message.userId !== parseInt(currentUserId))
const newCurrent = sentByCurrent.map(message => {
message.sentBySelf = true
return message
})
const newOthers = sentByOthers.map(message => {
message.sentBySelf = false
return message
})
const allMessages = newCurrent.concat(newOthers)
return allMessages
})
.then(allMsgsArray => {
setMessages(allMsgsArray)
})
.then(() => {
scrollToEnd()
})
}
useEffect(() => {
getPMs()
},[])
if (messages.length > 0) {
return (
<>
<div className="messagesContainer">
{messages.map(message => {
return <MsgCard key={message.id} message={message} />
})}
</div>
IGNORE THIS COMPONENT<MsgInput renderList={getPMs} />
</>
)
} else {
return (
<>
<div className="messagesContainer">
</div>
IGNORE THIS COMPONENT <MsgInput renderList={getPMs} />
</>
)
}
}
Upvotes: 0
Views: 664
Reputation: 41
Add sentBySelf
for the current object, so you will keep the sequence.
getAllPMs()
.then((allPMs) =>
allPMs.privateMessages.map((msg) => ({
...msg,
msg.userId === parseInt(currentUserId),
}))
) [...]
Here a live example:
https://codesandbox.io/s/ecstatic-hamilton-uck5n?fontsize=14&hidenavigation=1&theme=dark
Upvotes: 0
Reputation: 35626
Your issue is how you handle adding the sentBySelf
attribute to each message:
getAllPMs().then(allPMs => {
const sentByCurrent = allPMs.filter(message => message.userId === parseInt(currentUserId))
const sentByOthers = allPMs.filter(message => message.userId !== parseInt(currentUserId))
const newCurrent = sentByCurrent.map(message => {
message.sentBySelf = true
return message
})
const newOthers = sentByOthers.map(message => {
message.sentBySelf = false
return message
})
const allMessages = newCurrent.concat(newOthers)
return allMessages
})
You filter all sentByCurrent
then all sentByOthers
then when you rebuild the list you concat current
with others
. Ensuring all current
come before all others
.
You can use map instead to add the attribute without affecting the order.
const allPMs = [
{
"userId": 2,
"receiverId": 3,
"message": "first",
"id": 1
},
{
"userId": 3,
"receiverId": 2,
"message": "second",
"id": 2
},
{
"userId": 2,
"receiverId": 3,
"message": "third",
"id": 3
},
{
"userId": 2,
"receiverId": 3,
"message": "fourth",
"id": 4
},
{
"userId": 3,
"receiverId": 2,
"message": "fifth",
"id": 5
}
];
const currentUserId = "2";
const orderMaintained = allPMs.map(curr => ({...curr, sentBySelf: curr.userId === parseInt(currentUserId)}));
console.log(orderMaintained);
In your program this would look something like:
getAllPMs().then(allPMs => {
return allPMs.map(curr => ({...curr, sentBySelf: curr.userId === parseInt(currentUserId)}));
})
Upvotes: 1