diff --git a/lib/shared/typeahead-utils.js b/lib/shared/typeahead-utils.js
--- a/lib/shared/typeahead-utils.js
+++ b/lib/shared/typeahead-utils.js
@@ -2,17 +2,22 @@
 
 import type { RelativeMemberInfo } from '../types/thread-types';
 import SearchIndex from './search-index';
+import { threadOtherMembers } from './thread-utils';
 import { stringForUserExplicit } from './user-utils';
 
 function getTypeaheadUserSuggestions(
   userSearchIndex: SearchIndex,
-  usersInThread: $ReadOnlyArray<RelativeMemberInfo>,
-  typedPrefix: string,
+  threadMembers: $ReadOnlyArray<RelativeMemberInfo>,
+  viewerID: ?string,
+  typedUsernamePrefix: string,
 ): $ReadOnlyArray<RelativeMemberInfo> {
-  const userIDs = userSearchIndex.getSearchResults(typedPrefix);
+  const userIDs = userSearchIndex.getSearchResults(typedUsernamePrefix);
+  const usersInThread = threadOtherMembers(threadMembers, viewerID);
 
   return usersInThread
-    .filter(user => typedPrefix.length === 0 || userIDs.includes(user.id))
+    .filter(
+      user => typedUsernamePrefix.length === 0 || userIDs.includes(user.id),
+    )
     .sort((userA, userB) =>
       stringForUserExplicit(userA).localeCompare(stringForUserExplicit(userB)),
     );
diff --git a/web/chat/chat-input-bar.react.js b/web/chat/chat-input-bar.react.js
--- a/web/chat/chat-input-bar.react.js
+++ b/web/chat/chat-input-bar.react.js
@@ -15,7 +15,6 @@
   relativeMemberInfoSelectorForMembersOfThread,
 } from 'lib/selectors/user-selectors';
 import { localIDPrefix, trimMessage } from 'lib/shared/message-utils';
-import SearchIndex from 'lib/shared/search-index';
 import {
   threadHasPermission,
   viewerIsMember,
@@ -23,6 +22,7 @@
   threadActualMembers,
   checkIfDefaultMembersAreVoiced,
 } from 'lib/shared/thread-utils';
+import { getTypeaheadUserSuggestions } from 'lib/shared/typeahead-utils';
 import type { CalendarQuery } from 'lib/types/entry-types';
 import type { LoadingStatus } from 'lib/types/loading-types';
 import { messageTypes } from 'lib/types/message-types';
@@ -73,9 +73,8 @@
   +dispatchActionPromise: DispatchActionPromise,
   // async functions that hit server APIs
   +joinThread: (request: ClientThreadJoinRequest) => Promise<ThreadJoinPayload>,
-  +userSearchIndex: SearchIndex,
-  +threadMembers: $ReadOnlyArray<RelativeMemberInfo>,
   +typeaheadMatchedStrings: ?TypeaheadMatchedStrings,
+  +suggestedUsers: $ReadOnlyArray<RelativeMemberInfo>,
 };
 export type TypeaheadMatchedStrings = {
   +entireText: string,
@@ -331,15 +330,17 @@
     }
 
     let typeaheadTooltip;
-    if (this.props.typeaheadMatchedStrings && this.textarea) {
+    if (
+      this.props.suggestedUsers.length > 0 &&
+      this.props.typeaheadMatchedStrings &&
+      this.textarea
+    ) {
       typeaheadTooltip = (
         <TypeaheadTooltip
           inputState={this.props.inputState}
           textarea={this.textarea}
-          userSearchIndex={this.props.userSearchIndex}
-          threadMembers={this.props.threadMembers}
-          viewerID={this.props.viewerID}
           matchedStrings={this.props.typeaheadMatchedStrings}
+          suggestedUsers={this.props.suggestedUsers}
         />
       );
     }
@@ -549,13 +550,26 @@
         typeaheadRegexMatches !== null
           ? {
               entireText: typeaheadRegexMatches[0],
-              textBeforeAtSymbol: typeaheadRegexMatches[1],
-              usernamePrefix: typeaheadRegexMatches[2],
+              textBeforeAtSymbol:
+                typeaheadRegexMatches.groups?.textPrefix ?? '',
+              usernamePrefix: typeaheadRegexMatches.groups?.username ?? '',
             }
           : null,
       [typeaheadRegexMatches],
     );
 
+    const suggestedUsers: $ReadOnlyArray<RelativeMemberInfo> = React.useMemo(() => {
+      if (!typeaheadMatchedStrings) {
+        return [];
+      }
+      return getTypeaheadUserSuggestions(
+        userSearchIndex,
+        threadMembers,
+        viewerID,
+        typeaheadMatchedStrings.usernamePrefix,
+      );
+    }, [userSearchIndex, threadMembers, viewerID, typeaheadMatchedStrings]);
+
     return (
       <ChatInputBar
         {...props}
@@ -568,9 +582,8 @@
         userInfos={userInfos}
         dispatchActionPromise={dispatchActionPromise}
         joinThread={callJoinThread}
-        userSearchIndex={userSearchIndex}
-        threadMembers={threadMembers}
         typeaheadMatchedStrings={typeaheadMatchedStrings}
+        suggestedUsers={suggestedUsers}
       />
     );
   },
diff --git a/web/chat/typeahead-tooltip.react.js b/web/chat/typeahead-tooltip.react.js
--- a/web/chat/typeahead-tooltip.react.js
+++ b/web/chat/typeahead-tooltip.react.js
@@ -3,9 +3,6 @@
 import classNames from 'classnames';
 import * as React from 'react';
 
-import SearchIndex from 'lib/shared/search-index';
-import { threadOtherMembers } from 'lib/shared/thread-utils';
-import { getTypeaheadUserSuggestions } from 'lib/shared/typeahead-utils';
 import type { RelativeMemberInfo } from 'lib/types/thread-types';
 
 import Button from '../components/button.react';
@@ -20,21 +17,13 @@
 export type TypeaheadTooltipProps = {
   +inputState: InputState,
   +textarea: HTMLTextAreaElement,
-  +userSearchIndex: SearchIndex,
-  +threadMembers: $ReadOnlyArray<RelativeMemberInfo>,
-  +viewerID: ?string,
   +matchedStrings: TypeaheadMatchedStrings,
+  +suggestedUsers: $ReadOnlyArray<RelativeMemberInfo>,
 };
 
 function TypeaheadTooltip(props: TypeaheadTooltipProps): React.Node {
-  const {
-    inputState,
-    textarea,
-    userSearchIndex,
-    threadMembers,
-    viewerID,
-    matchedStrings,
-  } = props;
+  const { inputState, textarea, matchedStrings, suggestedUsers } = props;
+
   const [isVisibleForAnimation, setIsVisibleForAnimation] = React.useState(
     false,
   );
@@ -48,21 +37,8 @@
   const {
     entireText: matchedText,
     textBeforeAtSymbol: matchedTextBeforeAtSymbol,
-    usernamePrefix: matchedUsernamePrefix,
   } = matchedStrings;
 
-  const typedPrefix = matchedUsernamePrefix ?? '';
-
-  const suggestedUsers = React.useMemo(
-    () =>
-      getTypeaheadUserSuggestions(
-        userSearchIndex,
-        threadOtherMembers(threadMembers, viewerID),
-        typedPrefix,
-      ),
-    [userSearchIndex, threadMembers, viewerID, typedPrefix],
-  );
-
   const actions = React.useMemo(
     () =>
       getTypeaheadTooltipActions(