improvement: optimize ChannelMessageView and prevent sending a request for initial messages multiple times (has issues; see TODO)
This commit is contained in:
parent
3664b4e57b
commit
0090f5dc90
3 changed files with 77 additions and 34 deletions
|
@ -13,7 +13,8 @@ const intitialState = {
|
|||
glyph: "",
|
||||
title: "",
|
||||
content: ""
|
||||
}
|
||||
},
|
||||
messagesLoadedIn: []
|
||||
};
|
||||
|
||||
const reducer = (state = intitialState, payload) => {
|
||||
|
@ -74,6 +75,16 @@ const reducer = (state = intitialState, payload) => {
|
|||
};
|
||||
}
|
||||
|
||||
case 'channels/firstmessageload': {
|
||||
return {
|
||||
...state,
|
||||
messagesLoadedIn: [
|
||||
...state.messagesLoadedIn,
|
||||
payload.channelId
|
||||
]
|
||||
};
|
||||
}
|
||||
|
||||
case 'channels/updatepresence': {
|
||||
return {
|
||||
...state,
|
||||
|
|
|
@ -1,52 +1,83 @@
|
|||
import { useRef, useEffect, useState } from 'react';
|
||||
import { useDispatch } from "react-redux";
|
||||
import { PureComponent, createRef } from 'react';
|
||||
import { connect } from "react-redux";
|
||||
|
||||
import { authenticated } from "../../api/request";
|
||||
import { getJsonValue } from '../../common/environmentmanager';
|
||||
import Message from "../Message";
|
||||
|
||||
export default function ChannelMessageView({ messages, channelId }) {
|
||||
const invisibleBottomMessageRef = useRef();
|
||||
class ChannelMessageView extends PureComponent {
|
||||
constructor() {
|
||||
super();
|
||||
this.state = {
|
||||
isLoading: false
|
||||
};
|
||||
this.invisibleBottomMessageRef = createRef();
|
||||
this.scroller = createRef();
|
||||
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const dispatch = useDispatch();
|
||||
const scroller = useRef();
|
||||
this.onScroll = this.onScroll.bind(this);
|
||||
}
|
||||
|
||||
const loadOlderMessages = () => {
|
||||
if (isLoading) return;
|
||||
if (!channelId) return;
|
||||
setIsLoading(true);
|
||||
loadOlderMessages() {
|
||||
if (this.state.isLoading) return;
|
||||
if (!getJsonValue("loadMessages")) return; // parse as json to get boolean
|
||||
if (!this.props.channelId) return;
|
||||
this.setState({ isLoading: true });
|
||||
|
||||
const request = messages[0] ? `/api/v1/content/channel/${channelId}/messages?before=${messages[0]._id}` : `/api/v1/content/channel/${channelId}/messages`;
|
||||
const request = this.props.messages[0] ? `/api/v1/content/channel/${this.props.channelId}/messages?before=${this.props.messages[0]._id}` : `/api/v1/content/channel/${this.props.channelId}/messages`;
|
||||
|
||||
authenticated(request)
|
||||
.then((res) => {
|
||||
if (res.json.channelMessages)
|
||||
dispatch({
|
||||
this.props.dispatch({
|
||||
type: "messagestore/addmessagesback",
|
||||
messages: res.json.channelMessages.reverse(),
|
||||
channelId
|
||||
})
|
||||
channelId: this.props.channelId
|
||||
});
|
||||
})
|
||||
.then(() => {
|
||||
setIsLoading(false);
|
||||
this.setState({ isLoading: false });
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
const onScroll = () => {
|
||||
if (scroller.current.scrollTop === 0) {
|
||||
loadOlderMessages();
|
||||
firstTimeMessageLoad() {
|
||||
if (!this.props.channelId) return false;
|
||||
if (this.props.messagesLoadedIn.includes(this.props.channelId)) return false;
|
||||
this.props.dispatch({
|
||||
type: "channels/firstmessageload",
|
||||
channelId: this.props.channelId
|
||||
});
|
||||
this.loadOlderMessages();
|
||||
}
|
||||
|
||||
onScroll() {
|
||||
// TODO: this triggers when switching between channels so the firstmessageload check does not take effect
|
||||
if (this.scroller.current.scrollTop === 0)
|
||||
this.loadOlderMessages();
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.firstTimeMessageLoad();
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps) {
|
||||
if (prevProps.messages !== this.props.messages) {
|
||||
this.invisibleBottomMessageRef.current.scrollIntoView(true);
|
||||
}
|
||||
};
|
||||
if (prevProps.channelId !== this.props.channelId) {
|
||||
this.firstTimeMessageLoad();
|
||||
}
|
||||
}
|
||||
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
useEffect(loadOlderMessages, [channelId, dispatch]);
|
||||
|
||||
useEffect(() => {
|
||||
invisibleBottomMessageRef.current.scrollIntoView(true);
|
||||
}, [messages]);
|
||||
|
||||
return <div className="message-list" id="message-list" ref={ scroller } onScroll={ onScroll }>
|
||||
{messages.map(message => <Message message={message} key={message._id} />)}
|
||||
<div className="messages-scroll-div" ref={ invisibleBottomMessageRef }></div>
|
||||
</div>;
|
||||
render() {
|
||||
return <div className="message-list" id="message-list" ref={ this.scroller } onScroll={ this.onScroll }>
|
||||
{this.props.messages.map(message => <Message message={message} key={message._id} />)}
|
||||
<div className="messages-scroll-div" ref={ this.invisibleBottomMessageRef }></div>
|
||||
</div>;
|
||||
}
|
||||
}
|
||||
|
||||
export default connect((state) => {
|
||||
return {
|
||||
messagesLoadedIn: state.messagesLoadedIn
|
||||
};
|
||||
}, null)(ChannelMessageView);
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
const config = {
|
||||
apiUrl: "http://localhost:3000",
|
||||
gatewayUrl: "ws://localhost:3005/gateway",
|
||||
gatewayConnectionAttributes: ["PRESENCE_UPDATES"]
|
||||
gatewayConnectionAttributes: ["PRESENCE_UPDATES"],
|
||||
loadMessages: true
|
||||
};
|
||||
|
||||
export default config;
|
Loading…
Reference in a new issue