Reputation: 2476
I am creating a "log" screen that updates periodically in React. To make sure that the latest addition is always in view I would like the element to always be scrolled to the bottom:
I have the overflow working:
div.log {
height: 200px;
overflow: auto;
}
And the HTML:
render() {
return (
<div className="log">
<ul>
{this.props.log.map((log, i) =>
<li key={i}>
{log.message}
</li>
)}
</ul>
</div>
);
}
Here is my entire component:
import React from 'react';
export default class Log extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<div className="log">
<ul>
{this.props.log.map((log, i) =>
<li key={i}>
{log.message}
</li>
)}
</ul>
</div>
);
}
}
This all works fine, but doesn't stay scrolled down. I understand that I can use something similar to:
var element = document.getElementByClassName(".log");
element.scrollTop = element.scrollHeight;
But this only works once, I need to be scrolled to the bottom when the contents of ".log" updates.
Any help is much appreciated.
Upvotes: 1
Views: 80
Reputation: 112777
You can give a ref
to the topmost element of the Log
component and make sure it is scrolled to the bottom when the props update in componentDidUpdate
.
Example
class Log extends React.Component {
ref = React.createRef();
componentDidUpdate() {
this.ref.current.scrollTop = this.ref.current.scrollHeight;
}
render() {
return (
<div ref={this.ref} style={{ height: 50, overflowY: "scroll" }}>
<ul>
{this.props.log.map((log, i) => (
<li key={i}>{log.message}</li>
))}
</ul>
</div>
);
}
}
class App extends React.Component {
state = { logs: [] };
componentDidMount() {
setInterval(() => {
this.setState(prevState => {
return { logs: [...prevState.logs, { message: Math.random() }] };
});
}, 1000);
}
render() {
return <Log log={this.state.logs} />;
}
}
ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>
Upvotes: 2