I am working on a messaging app. I have a useState which is called 'messages' and it renders the messages from a certain chat on the screen. For now, every time a user sends a message, it is added to the messages useState but I want it to just be appended to the messages <div>
.
How can I append a message to the existing messages without changing the useState?
My main chat code looks somethings like this:
import React, { useState } from 'react';
export default function Main() {
const [messages, setMessages] = useState([]);
const [message, setMessage] = useState('');
// Message Managment
function chatInputPressed(e) {
if ((e.key === 'Enter' || e.keyCode === 13) && message !== '') { // Check if the user pressed the Enter key
setMessages(oldMsgs => ([message, ...oldMsgs])); // Insert the new message to the messages useState
setMessage(''); // Set the message to empty
}
}
return (
<div className='Main'>
<div className='messages'>
{messages.map(m => (
<div key='random-key' className='message' >{m}</div>
))}
</div>
<input
type="text"
id="message-input"
value={ message }
onChange={ (e) => setMessage(e.target.value) }
onKeyDown={ chatInputPressed }
>
</input>
</div>
);
}
I want to append a new message <div>
element to <div className='messages'>
instead of updating the messages like this setMessages(oldMsgs => ([message, ...oldMsgs]));
.
CodePudding user response:
You can handle it like below.
- You can keep a refs array to refer later to each message div element. Then use the index or messageId (create a unique one) to update the styles.
const [messageRefs, setMessageRefs] = useState([]);
- create and add a new
ref
for each message submission.
// Message Managment
function chatInputPressed(e) {
if ((e.key === "Enter" || e.keyCode === 13) && message !== "") {
// Check if the user pressed the Enter key
setMessageRefs((prev) => [createRef(null), ...prev]);
setMessages((oldMsgs) => [message, ...oldMsgs]); // Insert the new message to the messages useState
setMessage(""); // Set the message to empty
}
}
- For example if you wanted to change the color of a single message define a handler like below. In your case, it will be a callback for the API call to the backend.
function styleMessage(index) {
const mssageRef = messageRefs[index]?.current;
mssageRef.style.color = "red";
}
For example, I have added this as a click handler to each message to alter the color.