Merge pull request #55 from havfo/feat/chat-scrolling

Create HOC to handle chat scrolling
master
Håvar Aambø Fosstveit 2018-08-02 09:46:48 +02:00 committed by GitHub
commit 5c7b7a89df
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 68 additions and 19 deletions

View File

@ -1,14 +1,9 @@
import React, { Component } from 'react'; import React, { Component } from 'react';
import { compose } from 'redux';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import marked from 'marked'; import marked from 'marked';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import scrollToBottom from './scrollToBottom';
const scrollToBottom = () =>
{
const messagesDiv = document.getElementById('messages');
messagesDiv.scrollTop = messagesDiv.scrollHeight;
};
const linkRenderer = new marked.Renderer(); const linkRenderer = new marked.Renderer();
@ -22,16 +17,6 @@ linkRenderer.link = (href, title, text) =>
class MessageList extends Component class MessageList extends Component
{ {
componentDidMount()
{
scrollToBottom();
}
componentDidUpdate()
{
scrollToBottom();
}
getTimeString(time) getTimeString(time)
{ {
return `${(time.getHours() < 10 ? '0' : '')}${time.getHours()}:${(time.getMinutes() < 10 ? '0' : '')}${time.getMinutes()}`; return `${(time.getHours() < 10 ? '0' : '')}${time.getHours()}:${(time.getMinutes() < 10 ? '0' : '')}${time.getMinutes()}`;
@ -96,8 +81,9 @@ const mapStateToProps = (state) =>
}; };
}; };
const MessageListContainer = connect( const MessageListContainer = compose(
mapStateToProps connect(mapStateToProps),
scrollToBottom()
)(MessageList); )(MessageList);
export default MessageListContainer; export default MessageListContainer;

View File

@ -0,0 +1,63 @@
import React, { Component } from 'react';
import { findDOMNode } from 'react-dom';
/**
* A higher order component which scrolls the user to the bottom of the
* wrapped component, provided that the user already was at the bottom
* of the wrapped component. Useful for chats and similar use cases.
* @param {number} treshold The required distance from the bottom required.
*/
const scrollToBottom = (treshold = 0) => (WrappedComponent) =>
{
return class AutoScroller extends Component
{
constructor(props)
{
super(props);
this.ref = React.createRef();
}
getSnapshotBeforeUpdate()
{
// Check if the user has scrolled close enough to the bottom for
// us to scroll to the bottom or not.
return this.elem.scrollHeight - this.elem.scrollTop <=
this.elem.clientHeight - treshold;
}
scrollToBottom = () =>
{
// Scroll the user to the bottom of the wrapped element.
this.elem.scrollTop = this.elem.scrollHeight;
};
componentDidMount()
{
// eslint-disable-next-line react/no-find-dom-node
this.elem = findDOMNode(this.ref.current);
this.scrollToBottom();
}
componentDidUpdate(prevProps, prevState, atBottom)
{
if (atBottom)
{
this.scrollToBottom();
}
}
render()
{
return (
<WrappedComponent
ref={this.ref}
{...this.props}
/>
);
}
};
};
export default scrollToBottom;