diff --git a/lib/selectors/user-selectors.js b/lib/selectors/user-selectors.js
--- a/lib/selectors/user-selectors.js
+++ b/lib/selectors/user-selectors.js
@@ -7,8 +7,6 @@
   getAvatarForUser,
   getRandomDefaultEmojiAvatar,
 } from '../shared/avatar-utils.js';
-import SearchIndex from '../shared/search-index.js';
-import SentencePrefixSearchIndex from '../shared/sentence-prefix-search-index.js';
 import { getSingleOtherUser } from '../shared/thread-utils.js';
 import type { ClientEmojiAvatar } from '../types/avatar-types';
 import type { MinimallyEncodedRawThreadInfo } from '../types/minimally-encoded-thread-permissions-types.js';
@@ -170,30 +168,6 @@
     state.dataLoaded
   );
 
-const addUsersToSearchIndex = (
-  userInfos: UserInfos,
-  searchIndex: SearchIndex | SentencePrefixSearchIndex,
-): void => {
-  for (const id in userInfos) {
-    const { username } = userInfos[id];
-    if (!username) {
-      continue;
-    }
-    searchIndex.addEntry(id, username);
-  }
-};
-
-const userStoreMentionSearchIndex: (
-  state: BaseAppState<>,
-) => SentencePrefixSearchIndex = createSelector(
-  (state: BaseAppState<>) => state.userStore.userInfos,
-  (userInfos: UserInfos) => {
-    const searchIndex = new SentencePrefixSearchIndex();
-    addUsersToSearchIndex(userInfos, searchIndex);
-    return searchIndex;
-  },
-);
-
 const usersWithPersonalThreadSelector: (
   state: BaseAppState<>,
 ) => $ReadOnlySet<string> = createSelector(
@@ -240,7 +214,6 @@
   relativeMemberInfoSelectorForMembersOfThread,
   userInfoSelectorForPotentialMembers,
   isLoggedIn,
-  userStoreMentionSearchIndex,
   usersWithPersonalThreadSelector,
   savedEmojiAvatarSelectorForCurrentUser,
 };
diff --git a/lib/shared/mention-utils.js b/lib/shared/mention-utils.js
--- a/lib/shared/mention-utils.js
+++ b/lib/shared/mention-utils.js
@@ -1,9 +1,13 @@
 // @flow
 
+import * as React from 'react';
+
 import { oldValidUsernameRegexString } from './account-utils.js';
 import SentencePrefixSearchIndex from './sentence-prefix-search-index.js';
 import { threadOtherMembers } from './thread-utils.js';
 import { stringForUserExplicit } from './user-utils.js';
+import { useENSNames } from '../hooks/ens-cache.js';
+import { useUserSearchIndex } from '../selectors/nav-selectors.js';
 import { threadTypes } from '../types/thread-types-enum.js';
 import type {
   ChatMentionCandidates,
@@ -100,21 +104,34 @@
   return null;
 }
 
-function getMentionTypeaheadUserSuggestions(
-  userSearchIndex: SentencePrefixSearchIndex,
+const useENSNamesOptions = { allAtOnce: true };
+function useMentionTypeaheadUserSuggestions(
   threadMembers: $ReadOnlyArray<RelativeMemberInfo>,
   viewerID: ?string,
-  usernamePrefix: string,
+  typeaheadMatchedStrings: ?TypeaheadMatchedStrings,
 ): $ReadOnlyArray<MentionTypeaheadUserSuggestionItem> {
-  const userIDs = userSearchIndex.getSearchResults(usernamePrefix);
-  const usersInThread = threadOtherMembers(threadMembers, viewerID);
-
-  return usersInThread
-    .filter(user => usernamePrefix.length === 0 || userIDs.includes(user.id))
-    .sort((userA, userB) =>
-      stringForUserExplicit(userA).localeCompare(stringForUserExplicit(userB)),
-    )
-    .map(userInfo => ({ type: 'user', userInfo }));
+  const userSearchIndex = useUserSearchIndex(threadMembers);
+  const resolvedThredMembers = useENSNames(threadMembers, useENSNamesOptions);
+  const usernamePrefix: ?string = typeaheadMatchedStrings?.query;
+
+  return React.useMemo(() => {
+    // If typeaheadMatchedStrings is undefined, we want to return no results
+    if (usernamePrefix === undefined || usernamePrefix === null) {
+      return [];
+    }
+
+    const userIDs = userSearchIndex.getSearchResults(usernamePrefix);
+    const usersInThread = threadOtherMembers(resolvedThredMembers, viewerID);
+
+    return usersInThread
+      .filter(user => usernamePrefix.length === 0 || userIDs.includes(user.id))
+      .sort((userA, userB) =>
+        stringForUserExplicit(userA).localeCompare(
+          stringForUserExplicit(userB),
+        ),
+      )
+      .map(userInfo => ({ type: 'user', userInfo }));
+  }, [userSearchIndex, resolvedThredMembers, usernamePrefix, viewerID]);
 }
 
 function getMentionTypeaheadChatSuggestions(
@@ -157,31 +174,33 @@
   return { newText, newSelectionStart };
 }
 
-function getUserMentionsCandidates(
+function useUserMentionsCandidates(
   threadInfo: ThreadInfo,
   parentThreadInfo: ?ThreadInfo,
 ): $ReadOnlyArray<RelativeMemberInfo> {
-  if (threadInfo.type !== threadTypes.SIDEBAR) {
-    return threadInfo.members;
-  }
-  if (parentThreadInfo) {
-    return parentThreadInfo.members;
-  }
-  // This scenario should not occur unless the user logs out while looking at a
-  // sidebar. In that scenario, the Redux store may be cleared before ReactNav
-  // finishes transitioning away from the previous screen
-  return [];
+  return React.useMemo(() => {
+    if (threadInfo.type !== threadTypes.SIDEBAR) {
+      return threadInfo.members;
+    }
+    if (parentThreadInfo) {
+      return parentThreadInfo.members;
+    }
+    // This scenario should not occur unless the user logs out while looking at
+    // a sidebar. In that scenario, the Redux store may be cleared before
+    // ReactNav finishes transitioning away from the previous screen
+    return [];
+  }, [threadInfo, parentThreadInfo]);
 }
 
 export {
   markdownUserMentionRegex,
   isUserMentioned,
   extractUserMentionsFromText,
-  getMentionTypeaheadUserSuggestions,
+  useMentionTypeaheadUserSuggestions,
   getMentionTypeaheadChatSuggestions,
   getNewTextAndSelection,
   getTypeaheadRegexMatches,
-  getUserMentionsCandidates,
+  useUserMentionsCandidates,
   chatMentionRegex,
   encodeChatMentionText,
   decodeChatMentionText,
diff --git a/native/chat/chat-input-bar.react.js b/native/chat/chat-input-bar.react.js
--- a/native/chat/chat-input-bar.react.js
+++ b/native/chat/chat-input-bar.react.js
@@ -37,15 +37,14 @@
 } from 'lib/hooks/chat-mention-hooks.js';
 import { createLoadingStatusSelector } from 'lib/selectors/loading-selectors.js';
 import { threadInfoSelector } from 'lib/selectors/thread-selectors.js';
-import { userStoreMentionSearchIndex } from 'lib/selectors/user-selectors.js';
 import { colorIsDark } from 'lib/shared/color-utils.js';
 import { useEditMessage } from 'lib/shared/edit-messages-utils.js';
 import {
-  getMentionTypeaheadUserSuggestions,
+  useMentionTypeaheadUserSuggestions,
   getMentionTypeaheadChatSuggestions,
   getTypeaheadRegexMatches,
   type Selection,
-  getUserMentionsCandidates,
+  useUserMentionsCandidates,
   type MentionTypeaheadSuggestionItem,
   type TypeaheadMatchedStrings,
 } from 'lib/shared/mention-utils.js';
@@ -297,7 +296,6 @@
   +dispatchActionPromise: DispatchActionPromise,
   +joinThread: (request: ClientThreadJoinRequest) => Promise<ThreadJoinPayload>,
   +inputState: ?InputState,
-  +userSearchIndex: SentencePrefixSearchIndex,
   +userMentionsCandidates: $ReadOnlyArray<RelativeMemberInfo>,
   +chatMentionSearchIndex: SentencePrefixSearchIndex,
   +chatMentionCandidates: ChatMentionCandidates,
@@ -1258,8 +1256,6 @@
   const dispatchActionPromise = useDispatchActionPromise();
   const callJoinThread = useJoinThread();
 
-  const userSearchIndex = useSelector(userStoreMentionSearchIndex);
-
   const { getChatMentionSearchIndex } = useChatMentionContext();
   const chatMentionSearchIndex = getChatMentionSearchIndex(props.threadInfo);
 
@@ -1268,7 +1264,7 @@
     parentThreadID ? threadInfoSelector(state)[parentThreadID] : null,
   );
 
-  const userMentionsCandidates = getUserMentionsCandidates(
+  const userMentionsCandidates = useUserMentionsCandidates(
     props.threadInfo,
     parentThreadInfo,
   );
@@ -1303,50 +1299,43 @@
     [selectionState.text, selectionState.selection],
   );
 
-  const typeaheadResults: {
-    typeaheadMatchedStrings: ?TypeaheadMatchedStrings,
-    suggestions: $ReadOnlyArray<MentionTypeaheadSuggestionItem>,
-  } = React.useMemo(() => {
-    if (!typeaheadRegexMatches) {
+  const typeaheadMatchedStrings: ?TypeaheadMatchedStrings =
+    React.useMemo(() => {
+      if (typeaheadRegexMatches === null) {
+        return null;
+      }
       return {
-        typeaheadMatchedStrings: null,
-        suggestions: [],
+        textBeforeAtSymbol: typeaheadRegexMatches[1] ?? '',
+        query: typeaheadRegexMatches[4] ?? '',
       };
-    }
+    }, [typeaheadRegexMatches]);
 
-    const typeaheadMatchedStrings: TypeaheadMatchedStrings = {
-      textBeforeAtSymbol: typeaheadRegexMatches[1] ?? '',
-      query: typeaheadRegexMatches[4] ?? '',
-    };
+  const suggestedUsers = useMentionTypeaheadUserSuggestions(
+    userMentionsCandidates,
+    viewerID,
+    typeaheadMatchedStrings,
+  );
 
-    const suggestedUsers = getMentionTypeaheadUserSuggestions(
-      userSearchIndex,
-      userMentionsCandidates,
-      viewerID,
-      typeaheadMatchedStrings.query,
-    );
-    const suggestedChats = getMentionTypeaheadChatSuggestions(
-      chatMentionSearchIndex,
-      chatMentionCandidates,
-      typeaheadMatchedStrings.query,
-    );
-    const suggestions: $ReadOnlyArray<MentionTypeaheadSuggestionItem> = [
-      ...suggestedUsers,
-      ...suggestedChats,
-    ];
+  const suggestions: $ReadOnlyArray<MentionTypeaheadSuggestionItem> =
+    React.useMemo(() => {
+      if (!typeaheadRegexMatches || !typeaheadMatchedStrings) {
+        return [];
+      }
 
-    return {
+      const suggestedChats = getMentionTypeaheadChatSuggestions(
+        chatMentionSearchIndex,
+        chatMentionCandidates,
+        typeaheadMatchedStrings.query,
+      );
+
+      return [...suggestedUsers, ...suggestedChats];
+    }, [
+      chatMentionCandidates,
+      chatMentionSearchIndex,
+      typeaheadRegexMatches,
       typeaheadMatchedStrings,
-      suggestions,
-    };
-  }, [
-    chatMentionCandidates,
-    chatMentionSearchIndex,
-    typeaheadRegexMatches,
-    userMentionsCandidates,
-    userSearchIndex,
-    viewerID,
-  ]);
+      suggestedUsers,
+    ]);
 
   return (
     <ChatInputBar
@@ -1366,7 +1355,6 @@
       dispatchActionPromise={dispatchActionPromise}
       joinThread={callJoinThread}
       inputState={inputState}
-      userSearchIndex={userSearchIndex}
       userMentionsCandidates={userMentionsCandidates}
       chatMentionSearchIndex={chatMentionSearchIndex}
       chatMentionCandidates={chatMentionCandidates}
@@ -1379,8 +1367,8 @@
       messageEditingContext={messageEditingContext}
       selectionState={selectionState}
       setSelectionState={setSelectionState}
-      suggestions={typeaheadResults.suggestions}
-      typeaheadMatchedStrings={typeaheadResults.typeaheadMatchedStrings}
+      suggestions={suggestions}
+      typeaheadMatchedStrings={typeaheadMatchedStrings}
     />
   );
 }
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
@@ -16,14 +16,13 @@
 } from 'lib/hooks/chat-mention-hooks.js';
 import { createLoadingStatusSelector } from 'lib/selectors/loading-selectors.js';
 import { threadInfoSelector } from 'lib/selectors/thread-selectors.js';
-import { userStoreMentionSearchIndex } from 'lib/selectors/user-selectors.js';
 import {
-  getMentionTypeaheadUserSuggestions,
   getTypeaheadRegexMatches,
-  getUserMentionsCandidates,
+  useUserMentionsCandidates,
   getMentionTypeaheadChatSuggestions,
   type MentionTypeaheadSuggestionItem,
   type TypeaheadMatchedStrings,
+  useMentionTypeaheadUserSuggestions,
 } from 'lib/shared/mention-utils.js';
 import { localIDPrefix, trimMessage } from 'lib/shared/message-utils.js';
 import {
@@ -586,7 +585,6 @@
     const calendarQuery = useSelector(nonThreadCalendarQuery);
     const dispatchActionPromise = useDispatchActionPromise();
     const callJoinThread = useJoinThread();
-    const userSearchIndex = useSelector(userStoreMentionSearchIndex);
     const { getChatMentionSearchIndex } = useChatMentionContext();
     const chatMentionSearchIndex = getChatMentionSearchIndex(props.threadInfo);
 
@@ -595,7 +593,7 @@
       parentThreadID ? threadInfoSelector(state)[parentThreadID] : null,
     );
 
-    const userMentionsCandidates = getUserMentionsCandidates(
+    const userMentionsCandidates = useUserMentionsCandidates(
       props.threadInfo,
       parentThreadInfo,
     );
@@ -617,17 +615,16 @@
       [props.inputState.textCursorPosition, props.inputState.draft],
     );
 
-    const typeaheadMatchedStrings: ?TypeaheadMatchedStrings = React.useMemo(
-      () =>
-        typeaheadRegexMatches !== null
-          ? {
-              textBeforeAtSymbol:
-                typeaheadRegexMatches.groups?.textPrefix ?? '',
-              query: typeaheadRegexMatches.groups?.mentionText ?? '',
-            }
-          : null,
-      [typeaheadRegexMatches],
-    );
+    const typeaheadMatchedStrings: ?TypeaheadMatchedStrings =
+      React.useMemo(() => {
+        if (typeaheadRegexMatches === null) {
+          return null;
+        }
+        return {
+          textBeforeAtSymbol: typeaheadRegexMatches.groups?.textPrefix ?? '',
+          query: typeaheadRegexMatches.groups?.mentionText ?? '',
+        };
+      }, [typeaheadRegexMatches]);
 
     React.useEffect(() => {
       if (props.inputState.typeaheadState.keepUpdatingThreadMembers) {
@@ -644,16 +641,16 @@
       chatMentionCandidates,
     ]);
 
+    const suggestedUsers = useMentionTypeaheadUserSuggestions(
+      props.inputState.typeaheadState.frozenUserMentionsCandidates,
+      viewerID,
+      typeaheadMatchedStrings,
+    );
+
     const suggestions = React.useMemo(() => {
       if (!typeaheadMatchedStrings) {
         return ([]: $ReadOnlyArray<MentionTypeaheadSuggestionItem>);
       }
-      const suggestedUsers = getMentionTypeaheadUserSuggestions(
-        userSearchIndex,
-        props.inputState.typeaheadState.frozenUserMentionsCandidates,
-        viewerID,
-        typeaheadMatchedStrings.query,
-      );
       const suggestedChats = getMentionTypeaheadChatSuggestions(
         chatMentionSearchIndex,
         props.inputState.typeaheadState.frozenChatMentionsCandidates,
@@ -664,11 +661,9 @@
         ...suggestedChats,
       ]: $ReadOnlyArray<MentionTypeaheadSuggestionItem>);
     }, [
+      suggestedUsers,
       typeaheadMatchedStrings,
-      userSearchIndex,
-      props.inputState.typeaheadState.frozenUserMentionsCandidates,
       props.inputState.typeaheadState.frozenChatMentionsCandidates,
-      viewerID,
       chatMentionSearchIndex,
     ]);