From e180ac1f74baef86dbd6f4a792c3dfc336241dd4 Mon Sep 17 00:00:00 2001 From: vu-luong Date: Wed, 1 Jun 2022 01:09:06 +1000 Subject: [PATCH] fix infinite scrolling behavior, update example --- example/App.jsx | 131 ++++---------------------------- example/constants.jsx | 101 ++++++++++++++++++++++++ package.json | 4 +- src/MessageList/MessageList.jsx | 38 +++++---- 4 files changed, 141 insertions(+), 133 deletions(-) create mode 100644 example/constants.jsx diff --git a/example/App.jsx b/example/App.jsx index b547da8..7a1400e 100644 --- a/example/App.jsx +++ b/example/App.jsx @@ -5,6 +5,7 @@ import ChatList from '../src/ChatList/ChatList'; import ChatInput from '../src/ChatInput/ChatInput'; import MessageList from '../src/MessageList/MessageList'; import MessageListHeader from '../src/MessageListHeader/MessageListHeader'; +import { messagesToAppend, initialMessages, MAX_NUM_MESSAGES } from './constants'; import 'bootstrap/dist/css/bootstrap.min.css'; import '@fortawesome/fontawesome-free/js/fontawesome'; import '@fortawesome/fontawesome-free/js/solid'; @@ -15,89 +16,7 @@ import './App.css'; function App() { const [activeChannelId, setActiveChannelId] = useState(0); const [triggerScrollToBottom, setTriggerScrollToBottom] = useState(false); - const [messagesModel, setMessagesModel] = useState([ - { - isMe: true, - message: 'This is a message', - }, - { - isMe: false, - message: 'This is a reply', - }, - { - isMe: false, - message: 'This is a reply', - }, - { - isMe: false, - message: 'This is a reply', - }, - { - isMe: false, - message: 'This is a reply', - }, - { - isMe: false, - message: 'This is a reply', - }, - { - isMe: false, - message: 'This is a reply', - }, - { - isMe: false, - message: 'This is a reply', - }, - { - isMe: false, - message: 'This is a reply', - }, - { - isMe: false, - message: 'This is a reply', - }, - { - isMe: false, - message: 'This is a reply', - }, - { - isMe: false, - message: 'This is a reply', - }, - { - isMe: false, - message: 'This is a reply', - }, - { - isMe: false, - message: 'This is a reply', - }, - { - isMe: false, - message: 'This is a reply', - }, - { - isMe: false, - message: 'This is a reply', - }, - { - isMe: false, - message: 'This is a reply', - }, - { - isMe: false, - message: 'This is a reply', - }, - { - isMe: false, - message: 'This is a reply', - }, - { - isMe: false, - message: 'End', - }, - - ]); + const [messagesModel, setMessagesModel] = useState(initialMessages); const onItemClick = (id) => { setActiveChannelId(id); @@ -105,44 +24,25 @@ function App() { }; const onSend = (message) => { - // eslint-disable-next-line no-console - console.log(`onSend(${message})`); - setMessagesModel([ - { - isMe: true, - message: `${message}`, - }, - { - isMe: false, - message: `${message}`, - }, - { - isMe: false, - message: `${message}`, - }, - ...messagesModel, - ]); - }; - - const next = () => { - const message = 'new message'; - setTimeout(() => { + if (messagesModel.length <= 30) { setMessagesModel([ ...messagesModel, { isMe: true, - message: `${message}`, - }, - { - isMe: false, - message: `${message}`, - }, - { - isMe: false, - message: `${message}`, + message, }, ]); - }, 1500); + } + setTriggerScrollToBottom(!triggerScrollToBottom); + }; + + const next = () => { + if (messagesModel.length <= MAX_NUM_MESSAGES) { + setMessagesModel([ + ...messagesToAppend, + ...messagesModel, + ]); + } }; const channelsModel = [ @@ -186,6 +86,7 @@ function App() { triggerScrollToBottom={triggerScrollToBottom} channelId={activeChannelId} next={next} + hasMore={messagesModel.length <= MAX_NUM_MESSAGES} /> diff --git a/example/constants.jsx b/example/constants.jsx new file mode 100644 index 0000000..b6f6817 --- /dev/null +++ b/example/constants.jsx @@ -0,0 +1,101 @@ +const MAX_NUM_MESSAGES = 50; + +const initialMessages = [ + { + isMe: true, + message: 'This is a message', + }, + { + isMe: false, + message: 'This is a reply', + }, + { + isMe: false, + message: 'This is a reply', + }, + { + isMe: false, + message: 'This is a reply', + }, + { + isMe: false, + message: 'This is a reply', + }, + { + isMe: false, + message: 'This is a reply', + }, + { + isMe: false, + message: 'This is a reply', + }, + { + isMe: false, + message: 'This is a reply', + }, + { + isMe: false, + message: 'This is a reply', + }, + { + isMe: false, + message: 'This is a reply', + }, + { + isMe: false, + message: 'This is a reply', + }, + { + isMe: false, + message: 'This is a reply', + }, + { + isMe: false, + message: 'This is a reply', + }, + { + isMe: false, + message: 'This is a reply', + }, + { + isMe: false, + message: 'This is a reply', + }, + { + isMe: false, + message: 'This is a reply', + }, + { + isMe: false, + message: 'This is a reply', + }, + { + isMe: false, + message: 'This is a reply', + }, + { + isMe: false, + message: 'End', + }, +]; + +const messagesToAppend = [ + { + isMe: true, + message: 'Message', + }, + { + isMe: false, + message: 'Message', + }, + { + isMe: false, + message: 'Message', + }, +]; + +export { + initialMessages, + messagesToAppend, + MAX_NUM_MESSAGES, +}; diff --git a/package.json b/package.json index f2b5447..67a845b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-bootstrap-chat-ui", - "version": "0.0.8", + "version": "0.0.9", "description": "UIkit for chat application using react and bootstrap", "main": "dist/bundle/cjs/react-bootstrap-chat-ui.min.js", "module": "dist/esm/index.js", @@ -47,7 +47,7 @@ "bootstrap": "4.6.0", "classnames": "^2.3.1", "prop-types": "^15.8.1", - "react-infinite-scroll-component": "^6.1.0", + "react-infinite-scroller": "^1.2.6", "react-uuid": "^1.0.2" } } diff --git a/src/MessageList/MessageList.jsx b/src/MessageList/MessageList.jsx index 323dc88..c7a9cd8 100644 --- a/src/MessageList/MessageList.jsx +++ b/src/MessageList/MessageList.jsx @@ -1,12 +1,12 @@ -import React, { useRef, useState } from 'react'; -import InfiniteScroll from 'react-infinite-scroll-component'; +import React, { useEffect, useRef, useState } from 'react'; +import InfiniteScroll from 'react-infinite-scroller'; import PropTypes from 'prop-types'; import MessageBubble from '../MessageBubble/MessageBubble'; import '../style.css'; function MessageList(props) { const { - dataSource, triggerScrollToBottom, next, + dataSource, triggerScrollToBottom, next, hasMore, } = props; const messagesEnd = useRef(null); @@ -16,34 +16,38 @@ function MessageList(props) { messagesEnd.current?.scrollIntoView({ behavior: 'smooth', block: 'nearest', inline: 'start' }); }; - if (triggerScrollToBottom !== prevTriggerScroll) { - scrollToBottom(); - setPrevTriggerScroll(triggerScrollToBottom); - } + useEffect(() => { + if (triggerScrollToBottom !== prevTriggerScroll) { + scrollToBottom(); + setPrevTriggerScroll(triggerScrollToBottom); + } + }, [triggerScrollToBottom]); return ( -
-
+
Loading ...
} - scrollableTarget="scrollableDiv" + useWindow={false} + threshold={25} + initialLoad={false} + isReverse > { dataSource.map((item, i) => ( )) } +
); } @@ -52,12 +56,14 @@ MessageList.propTypes = { dataSource: PropTypes.arrayOf(MessageBubble.propTypes.data), triggerScrollToBottom: PropTypes.bool, next: PropTypes.func, + hasMore: PropTypes.bool, }; MessageList.defaultProps = { dataSource: [], triggerScrollToBottom: false, next: null, + hasMore: false, }; export default MessageList;