diff --git a/_locales/en/messages.json b/_locales/en/messages.json
index 79e5a0c0c..c23feed5e 100644
--- a/_locales/en/messages.json
+++ b/_locales/en/messages.json
@@ -462,5 +462,7 @@
   "reactionPopupOne": "$name$",
   "reactionPopupTwo": "$name$ & $name2$",
   "reactionPopupThree": "$name$, $name2$ & $name3$",
-  "reactionPopupMany": "$name$, $name2$, $name3$ &"
+  "reactionPopupMany": "$name$, $name2$, $name3$ &",
+  "reactionListCountSingular": "And $otherSingular$ has reacted to this message",
+  "reactionListCountPlural": "And $otherPlural$ have reacted to this message"
 }
diff --git a/ts/components/dialog/ReactListModal.tsx b/ts/components/dialog/ReactListModal.tsx
index fc1787297..1d73740e4 100644
--- a/ts/components/dialog/ReactListModal.tsx
+++ b/ts/components/dialog/ReactListModal.tsx
@@ -14,7 +14,7 @@ import {
 } from '../../state/ducks/modalDialog';
 import { SortedReactionList } from '../../types/Reaction';
 import { nativeEmojiData } from '../../util/emoji';
-import { sendMessageReaction } from '../../util/reactions';
+import { sendMessageReaction, SOGSReactorsFetchCount } from '../../util/reactions';
 import { Avatar, AvatarSize } from '../avatar/Avatar';
 import { Flex } from '../basic/Flex';
 import { ContactName } from '../conversation/ContactName';
@@ -36,12 +36,12 @@ const StyledReactionsContainer = styled.div`
 
 const StyledSendersContainer = styled(Flex)`
   width: 100%;
-  min-height: 350px;
+  min-height: 332px;
   height: 100%;
   max-height: 496px;
   overflow-x: hidden;
   overflow-y: auto;
-  padding: 0 16px 32px;
+  padding: 0 16px 16px;
 `;
 
 const StyledReactionBar = styled(Flex)`
@@ -159,6 +159,26 @@ const ReactionSenders = (props: ReactionSendersProps) => {
   );
 };
 
+const StyledCountText = styled.p`
+  color: var(--color-text-subtle);
+  text-align: center;
+  margin: 16px auto 0;
+`;
+
+const CountText = ({ count }: { count: number }) => {
+  return (
+    <StyledCountText>
+      {count > SOGSReactorsFetchCount + 1
+        ? window.i18n('reactionListCountPlural', [
+            window.i18n('otherPlural', [String(count - SOGSReactorsFetchCount)]),
+          ])
+        : window.i18n('reactionListCountSingular', [
+            window.i18n('otherSingular', [String(count - SOGSReactorsFetchCount)]),
+          ])}
+    </StyledCountText>
+  );
+};
+
 type Props = {
   reaction: string;
   messageId: string;
@@ -182,6 +202,7 @@ const handleSenders = (senders: Array<string>, me: string) => {
   return updatedSenders;
 };
 
+// tslint:disable-next-line: max-func-body-length
 export const ReactListModal = (props: Props): ReactElement => {
   const { reaction, messageId } = props;
 
@@ -189,6 +210,7 @@ export const ReactListModal = (props: Props): ReactElement => {
   const reactionsMap = (reactions && Object.fromEntries(reactions)) || {};
   const [currentReact, setCurrentReact] = useState('');
   const [reactAriaLabel, setReactAriaLabel] = useState<string | undefined>();
+  const [count, setCount] = useState<number | null>(null);
   const [senders, setSenders] = useState<Array<string>>([]);
   const me = UserUtils.getOurPubKeyStrFromCache();
 
@@ -230,7 +252,20 @@ export const ReactListModal = (props: Props): ReactElement => {
     if (senders.length > 0 && (!reactionsMap[currentReact]?.senders || isEmpty(_senders))) {
       setSenders([]);
     }
-  }, [currentReact, me, reaction, msgProps?.sortedReacts, reactionsMap, senders]);
+
+    if (reactionsMap[currentReact]?.count && count !== reactionsMap[currentReact]?.count) {
+      setCount(reactionsMap[currentReact].count);
+    }
+  }, [
+    count,
+    currentReact,
+    me,
+    reaction,
+    reactionsMap[currentReact]?.count,
+    msgProps?.sortedReacts,
+    reactionsMap,
+    senders,
+  ]);
 
   if (!msgProps) {
     return <></>;
@@ -320,6 +355,7 @@ export const ReactListModal = (props: Props): ReactElement => {
                 handleClose={handleClose}
               />
             )}
+            {isPublic && count && count > SOGSReactorsFetchCount && <CountText count={count} />}
           </StyledSendersContainer>
         )}
       </StyledReactListContainer>
diff --git a/ts/models/conversation.ts b/ts/models/conversation.ts
index d1fff96b4..5719dfcca 100644
--- a/ts/models/conversation.ts
+++ b/ts/models/conversation.ts
@@ -93,6 +93,7 @@ import {
 } from '../session/apis/open_group_api/sogsv3/knownBlindedkeys';
 import { sogsV3FetchPreviewAndSaveIt } from '../session/apis/open_group_api/sogsv3/sogsV3FetchFile';
 import { Reaction } from '../types/Reaction';
+import { handleMessageReaction } from '../util/reactions';
 
 export class ConversationModel extends Backbone.Model<ConversationAttributes> {
   public updateLastMessage: () => any;
@@ -736,7 +737,7 @@ export class ConversationModel extends Backbone.Model<ConversationAttributes> {
 
         const chatMessagePrivate = new VisibleMessage(chatMessageParams);
         await getMessageQueue().sendToPubKey(destinationPubkey, chatMessagePrivate);
-
+        await handleMessageReaction(reaction, UserUtils.getOurPubKeyStrFromCache(), true);
         return;
       }
 
@@ -748,6 +749,7 @@ export class ConversationModel extends Backbone.Model<ConversationAttributes> {
         });
         // we need the return await so that errors are caught in the catch {}
         await getMessageQueue().sendToGroup(closedGroupVisibleMessage);
+        await handleMessageReaction(reaction, UserUtils.getOurPubKeyStrFromCache(), true);
         return;
       }
 
diff --git a/ts/receiver/dataMessage.ts b/ts/receiver/dataMessage.ts
index 4ed6222df..3c0ccdac0 100644
--- a/ts/receiver/dataMessage.ts
+++ b/ts/receiver/dataMessage.ts
@@ -321,7 +321,11 @@ async function handleSwarmMessage(
     // this call has to be made inside the queueJob!
     // We handle reaction DataMessages separately
     if (!msgModel.get('isPublic') && rawDataMessage.reaction) {
-      await handleMessageReaction(rawDataMessage.reaction, msgModel.get('source'));
+      await handleMessageReaction(
+        rawDataMessage.reaction,
+        msgModel.get('source'),
+        isUsFromCache(msgModel.get('source'))
+      );
       confirm();
       return;
     }
diff --git a/ts/test/session/unit/reactions/ReactionMessage_test.ts b/ts/test/session/unit/reactions/ReactionMessage_test.ts
index dfd2fd1aa..63bfa3748 100644
--- a/ts/test/session/unit/reactions/ReactionMessage_test.ts
+++ b/ts/test/session/unit/reactions/ReactionMessage_test.ts
@@ -54,7 +54,8 @@ describe('ReactionMessage', () => {
     // Handling reaction
     const updatedMessage = await handleMessageReaction(
       reaction as SignalService.DataMessage.IReaction,
-      ourNumber
+      ourNumber,
+      true
     );
 
     expect(updatedMessage?.get('reacts'), 'original message should have reacts').to.not.be
@@ -85,7 +86,8 @@ describe('ReactionMessage', () => {
     // Handling reaction
     const updatedMessage = await handleMessageReaction(
       reaction as SignalService.DataMessage.IReaction,
-      ourNumber
+      ourNumber,
+      true
     );
 
     expect(updatedMessage?.get('reacts'), 'original message reacts should be undefined').to.be
diff --git a/ts/types/LocalizerKeys.ts b/ts/types/LocalizerKeys.ts
index 03e4521b4..766227d00 100644
--- a/ts/types/LocalizerKeys.ts
+++ b/ts/types/LocalizerKeys.ts
@@ -69,6 +69,7 @@ export type LocalizerKeys =
   | 'notificationsSettingsTitle'
   | 'ringing'
   | 'tookAScreenshot'
+  | 'reactionListCountPlural'
   | 'from'
   | 'thisMonth'
   | 'next'
@@ -277,6 +278,7 @@ export type LocalizerKeys =
   | 'mainMenuFile'
   | 'callMissed'
   | 'getStarted'
+  | 'reactionListCountSingular'
   | 'unblockUser'
   | 'blockUser'
   | 'clearAllConfirmationTitle'
diff --git a/ts/types/Reaction.ts b/ts/types/Reaction.ts
index 7357e54aa..d9788743e 100644
--- a/ts/types/Reaction.ts
+++ b/ts/types/Reaction.ts
@@ -124,7 +124,7 @@ export type ReactionList = Record<
     count: number;
     index: number; // relies on reactsIndex in the message model
     senders: Array<string>;
-    you?: boolean; // whether we are in the senders because sometimes we dont have the full list of senders yet.
+    you: boolean; // whether we are in the senders list, used within 1-1 and closed groups for ignoring duplicate data messages, used within opengroups since we dont always have the full list of senders.
   }
 >;
 
diff --git a/ts/util/reactions.ts b/ts/util/reactions.ts
index fb0943c96..1d1b50a05 100644
--- a/ts/util/reactions.ts
+++ b/ts/util/reactions.ts
@@ -139,7 +139,8 @@ export const sendMessageReaction = async (messageId: string, emoji: string) => {
  */
 export const handleMessageReaction = async (
   reaction: SignalService.DataMessage.IReaction,
-  sender: string
+  sender: string,
+  you: boolean
 ) => {
   if (!reaction.emoji) {
     window?.log?.warn(`There is no emoji for the reaction ${reaction}.`);
@@ -151,22 +152,27 @@ export const handleMessageReaction = async (
     return;
   }
 
-  if (originalMessage.get('isPublic')) {
-    window.log.warn("handleMessageReaction() shouldn't be used in opengroups");
-    return;
-  }
-
   const reacts: ReactionList = originalMessage.get('reacts') ?? {};
   reacts[reaction.emoji] = reacts[reaction.emoji] || { count: null, senders: [] };
   const details = reacts[reaction.emoji] ?? {};
   const senders = details.senders;
   let count = details.count || 0;
 
-  window.log.info(
-    `${sender} ${reaction.action === Action.REACT ? 'added' : 'removed'} a ${
-      reaction.emoji
-    } reaction`
-  );
+  if (originalMessage.get('isPublic')) {
+    window.log.warn("handleMessageReaction() shouldn't be used in opengroups");
+    return;
+  } else {
+    if (details.you && senders.includes(sender)) {
+      if (reaction.action === Action.REACT) {
+        window.log.warn('Received duplicate message for your reaction. Ignoring it');
+        return;
+      } else {
+        details.you = false;
+      }
+    } else {
+      details.you = you;
+    }
+  }
 
   switch (reaction.action) {
     case Action.REACT:
@@ -191,6 +197,7 @@ export const handleMessageReaction = async (
   if (count > 0) {
     reacts[reaction.emoji].count = count;
     reacts[reaction.emoji].senders = details.senders;
+    reacts[reaction.emoji].you = details.you;
 
     if (details && details.index === undefined) {
       reacts[reaction.emoji].index = originalMessage.get('reactsIndex') ?? 0;
@@ -206,6 +213,14 @@ export const handleMessageReaction = async (
   });
 
   await originalMessage.commit();
+
+  if (!you) {
+    window.log.info(
+      `${sender} ${reaction.action === Action.REACT ? 'added' : 'removed'} a ${
+        reaction.emoji
+      } reaction`
+    );
+  }
   return originalMessage;
 };