Skip to content

Commit 691915c

Browse files
chore: cleanup and document event subscriptions in channel component (#1976)
* fix: typing indicator may be shown when user not typing * fix: badly scoped variable * chore: add comments and avoid resyncChannel as a dependency --------- Co-authored-by: vanGalilea <[email protected]>
1 parent b7fd437 commit 691915c

File tree

1 file changed

+74
-57
lines changed

1 file changed

+74
-57
lines changed

package/src/components/Channel/Channel.tsx

Lines changed: 74 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -637,7 +637,7 @@ const ChannelWithContext = <
637637
} else {
638638
setThread(null);
639639
}
640-
}, [threadPropsExists]);
640+
}, [threadPropsExists, shouldSyncChannel]);
641641

642642
const handleAppBackground = useCallback(() => {
643643
const channelData = channel.data as
@@ -739,70 +739,61 @@ const ChannelWithContext = <
739739
),
740740
).current;
741741

742-
const connectionChangedHandler = () => {
743-
if (shouldSyncChannel) {
744-
resyncChannel();
745-
}
746-
};
747-
748-
const handleEvent: EventHandler<StreamChatGenerics> = (event) => {
749-
if (shouldSyncChannel) {
750-
if (thread) {
751-
const updatedThreadMessages =
752-
(thread.id && channel && channel.state.threads[thread.id]) || threadMessages;
753-
setThreadMessages(updatedThreadMessages);
754-
}
755-
756-
if (channel && thread && event.message?.id === thread.id) {
757-
const updatedThread = channel.state.formatMessage(event.message);
758-
setThread(updatedThread);
759-
}
760-
761-
if (event.type === 'typing.start' || event.type === 'typing.stop') {
762-
copyTypingState();
763-
} else if (event.type === 'message.read') {
764-
copyReadState();
765-
} else if (event.type === 'message.new') {
766-
copyMessagesState();
767-
} else if (channel) {
768-
copyChannelState();
769-
}
770-
}
771-
};
772-
742+
// subscribe to specific channel events
773743
useEffect(() => {
774744
const channelSubscriptions: Array<ReturnType<ChannelType['on']>> = [];
775-
const clientSubscriptions: Array<ReturnType<StreamChat['on']>> = [];
745+
if (channel && shouldSyncChannel) {
746+
channelSubscriptions.push(channel.on('message.new', copyMessagesState));
747+
channelSubscriptions.push(channel.on('message.read', copyReadState));
748+
channelSubscriptions.push(channel.on('typing.start', copyTypingState));
749+
channelSubscriptions.push(channel.on('typing.stop', copyTypingState));
750+
}
751+
return () => {
752+
channelSubscriptions.forEach((s) => s.unsubscribe());
753+
};
754+
}, [channelId, shouldSyncChannel]);
776755

777-
if (!channel) return;
756+
// subscribe to the generic all channel event
757+
useEffect(() => {
758+
const handleEvent: EventHandler<StreamChatGenerics> = (event) => {
759+
if (shouldSyncChannel) {
760+
if (thread) {
761+
const updatedThreadMessages =
762+
(thread.id && channel && channel.state.threads[thread.id]) || threadMessages;
763+
setThreadMessages(updatedThreadMessages);
764+
}
778765

779-
clientSubscriptions.push(
780-
client.on('channel.deleted', (event) => {
781-
if (event.cid === channel.cid) {
782-
setDeleted(true);
766+
if (channel && thread && event.message?.id === thread.id) {
767+
const updatedThread = channel.state.formatMessage(event.message);
768+
setThread(updatedThread);
783769
}
784-
}),
785-
);
786770

787-
if (enableOfflineSupport) {
788-
clientSubscriptions.push(DBSyncManager.onSyncStatusChange(connectionChangedHandler));
789-
} else {
790-
clientSubscriptions.push(
791-
client.on('connection.changed', (event) => {
792-
if (event.online) {
793-
connectionChangedHandler();
794-
}
795-
}),
796-
);
797-
}
771+
// only update channel state if the events are not the previously subscribed useEffect's subscription events
772+
if (
773+
channel &&
774+
event.type !== 'message.new' &&
775+
event.type !== 'message.read' &&
776+
event.type !== 'typing.start' &&
777+
event.type !== 'typing.stop'
778+
) {
779+
copyChannelState();
780+
}
781+
}
782+
};
783+
const { unsubscribe } = channel.on(handleEvent);
784+
return unsubscribe;
785+
}, [channelId, thread?.id, shouldSyncChannel]);
798786

799-
channelSubscriptions.push(channel.on(handleEvent));
787+
// subscribe to channel.deleted event
788+
useEffect(() => {
789+
const { unsubscribe } = client.on('channel.deleted', (event) => {
790+
if (event.cid === channel?.cid) {
791+
setDeleted(true);
792+
}
793+
});
800794

801-
return () => {
802-
clientSubscriptions.forEach((s) => s.unsubscribe());
803-
channelSubscriptions.forEach((s) => s.unsubscribe());
804-
};
805-
}, [channelId, connectionChangedHandler, handleEvent]);
795+
return unsubscribe;
796+
}, [channelId]);
806797

807798
const channelQueryCallRef = useRef(
808799
async (
@@ -1076,6 +1067,32 @@ const ChannelWithContext = <
10761067
setSyncingChannel(false);
10771068
};
10781069

1070+
// resync channel is added to ref so that it can be used in useEffect without adding it as a dependency
1071+
const resyncChannelRef = useRef(resyncChannel);
1072+
resyncChannelRef.current = resyncChannel;
1073+
1074+
useEffect(() => {
1075+
const connectionChangedHandler = () => {
1076+
if (shouldSyncChannel) {
1077+
resyncChannelRef.current();
1078+
}
1079+
};
1080+
let connectionChangedSubscription: ReturnType<ChannelType['on']>;
1081+
1082+
if (enableOfflineSupport) {
1083+
connectionChangedSubscription = DBSyncManager.onSyncStatusChange(connectionChangedHandler);
1084+
} else {
1085+
connectionChangedSubscription = client.on('connection.changed', (event) => {
1086+
if (event.online) {
1087+
connectionChangedHandler();
1088+
}
1089+
});
1090+
}
1091+
return () => {
1092+
connectionChangedSubscription.unsubscribe();
1093+
};
1094+
}, [enableOfflineSupport, shouldSyncChannel]);
1095+
10791096
const reloadChannel = () =>
10801097
channelQueryCallRef.current(async () => {
10811098
setLoading(true);

0 commit comments

Comments
 (0)