I have a container that fills the height of the page. This container has display flex and flex direction column. Then I have a Messages component which is a ul with one li per message plus a special AlwaysScrollToBottom component as the last child that, with the help of useEffect, scrolls to the bottom of the list.
const AlwaysScrollToBottom = () => {
const elementRef = useRef();
useEffect(() => elementRef.current.scrollIntoView());
return <div ref={elementRef} />;
};
const Messages = ({ items }) => (
<ul>
{items.map(({id, text}) => <li key={id}>{text}</li>)}
<AlwaysScrollToBottom />
</ul>
)
const App = () => (
<div className="container">
<Messages items={[...]}>
<MessageComposer />
</div>
)
The CSS is
.container {
display: flex;
height: 100vh;
flex-direction: column;
}
ul {
flex-grow: 1;
overflow-y: auto;
}
MessageComposer has been omitted for brevity, it contains the form, the input field, etc. to send messages.