Reputation: 406
I'm currently working on a chat app for school, but I want to make it scroll to the bottom automatically as most chat apps do. I've tried every solution I can find so far, and I have only been getting react errors. I'm new to react so there could be some mistakes I don't realize I'm making. Here is what I have
class Messages extends React.Component {
updateScroll() {
let element = document.querySelector(".messages");
element.scrollTop = element.scrollHeight;
}
render() {
const messages = store.getState().messages.map((msg) => {
this.updateScroll();
return (
<Message
name={msg.displayName}
message={msg.text}
time={msg.timestamp}
pic={msg.pic}
key={msg.timestamp}
clas={msg.who}
/>
);
});
return (
<div className="messages">
<div className="chat">
</div>
<div className="sendMessage">
<input
type="text"
placeholder="Message epic channel"
className="pendingMessage"
onKeyPress={this.handleKeyDown}
/>
<button onClick={this.handleMessageSend}>Send</button>
</div>
</div>
);
}
}
export default Messages;
Here is my GitHub link if you want the full code as well. https://github.com/dougalcaleb/react-chat-app
Thanks!
Upvotes: 1
Views: 1706
Reputation: 766
Try calling the updateScroll
function inside componentDidMount
if you are just fetching messages from state.
You can also use a ref to your message
div and get the height from there instead of using querySelector
Upvotes: 0
Reputation: 36
create a dummy div below messages.
<div ref={messagesEndRef}></div>
const messagesEndRef = useRef(null)
const [msglist, setMsglist] = useState([]);
if msglist is the list of new messages, use useEffect to handle the change.
useEffect(() => {
messagesEndRef.current.scrollIntoView({ behavior: 'smooth' })
}, [msglist])
Upvotes: 1
Reputation: 411
You should use refs instead of document query
class Messages extends React.Component {
constructor() {
super()
this.messagesRef = React.createRef()
}
updateScroll() {
this.messagesRef.current.scrollTo(0, this.messagesRef.current.scrollHeight)
}
render() {
const messages = store.getState().messages.map((msg) => {
this.updateScroll();
return (
<Message
name={msg.displayName}
message={msg.text}
time={msg.timestamp}
pic={msg.pic}
key={msg.timestamp}
clas={msg.who}
/>
);
});
return (
<div ref={this.messagesRef} className="messages">
<div className="chat">
</div>
<div className="sendMessage">
<input
type="text"
placeholder="Message epic channel"
className="pendingMessage"
onKeyPress={this.handleKeyDown}
/>
<button onClick={this.handleMessageSend}>Send</button>
</div>
</div>
);
}
}
export default Messages;
Can you try that using ref + scrollTo ?
Upvotes: 1
Reputation: 608
I suggest you should do this with css
The chatbox content need the following markup, where the content is aligned to bottom.
.container {
height: 100px;
overflow: auto;
display: flex;
flex-direction: column-reverse;
}
Upvotes: 2