I have a Message
ponent that displays all the messages(ining and outgoing) in one thread.
I would like the last message/a newly typed message/ining message to always appear at the bottom of the conversation. Kind of like what all chats/messaging apps do.
Here is my code:
import React, { useRef } from "react";
const dummy = useRef();
...
dummy?.current?.scrollIntoView(true, {
behaviour: "auto",
});
...
<div className="">
<Paper
elevation={0}
sx={{
backgroundColor: "#fafafa",
maxHeight: 200,
overflow: "auto",
}}
>
{messages.map((message, idx) => (
<div key={idx} ref={dummy}>
<Message message={message} name={name} />
</div>
))}
{/* I tried this also
<div ref={dummy}></div> */}
</Paper>
</div>
I want all the messages that can fit in the parent div with maxHeight: 200
to be displayed with the last message just at the bottom when I click on the conversation/thread. Currently, the WHOLE page scrolls to bottom instead of just the messages in the thread. The page should remain stationary.
How do I do this?
I have a Message
ponent that displays all the messages(ining and outgoing) in one thread.
I would like the last message/a newly typed message/ining message to always appear at the bottom of the conversation. Kind of like what all chats/messaging apps do.
Here is my code:
import React, { useRef } from "react";
const dummy = useRef();
...
dummy?.current?.scrollIntoView(true, {
behaviour: "auto",
});
...
<div className="">
<Paper
elevation={0}
sx={{
backgroundColor: "#fafafa",
maxHeight: 200,
overflow: "auto",
}}
>
{messages.map((message, idx) => (
<div key={idx} ref={dummy}>
<Message message={message} name={name} />
</div>
))}
{/* I tried this also
<div ref={dummy}></div> */}
</Paper>
</div>
I want all the messages that can fit in the parent div with maxHeight: 200
to be displayed with the last message just at the bottom when I click on the conversation/thread. Currently, the WHOLE page scrolls to bottom instead of just the messages in the thread. The page should remain stationary.
How do I do this?
Share Improve this question edited Apr 16, 2022 at 4:52 Youzef asked Apr 15, 2022 at 19:58 YouzefYouzef 8582 gold badges10 silver badges27 bronze badges 03 Answers
Reset to default 13 +50The problem is you are passing the ref
to the div
element in which the Message
ponent is rendered. I would suggest you use a dummy div
at the end of your chat and then scroll to that whenever your ponent is updated.
return (
<div
className="messagesWrapper"
style={{ background: "white", border: "2px red solid" }}
>
{messages.map((message) => (
<span key={message}>{message}</span>
))}
<div ref={dummy} />
</div>
);
The ref element is updated in useEffect.
const dummy = useRef(null);
useEffect(() => {
dummy.current.scrollIntoView({ behavior: "smooth" });
}, [messages]);
Attaching a sandbox for reference.
I think this will work:
React.useEffect(() => {
dummy.current.scrollTop = dummy.current.scrollHeight
})
So what you can do is create a useRef and then initiate it as null
Then when you .map over your array to render the objects, run a function to check if it's the last item in the array
If it is the last object in the array, attach the ref to it
Then have a useEffect with the ref in the dependency array
If the useRef get's set with a new value, from the .map,in your useEffect, have a scrollTo behavior, smooth, function that scrolls to it