diff --git a/lib/selectors/nav-selectors.js b/lib/selectors/nav-selectors.js
--- a/lib/selectors/nav-selectors.js
+++ b/lib/selectors/nav-selectors.js
@@ -1,13 +1,14 @@
 // @flow
 
-import _keyBy from 'lodash/fp/keyBy.js';
-import _mapValues from 'lodash/fp/mapValues.js';
 import * as React from 'react';
 import { createSelector } from 'reselect';
 
 import { useENSNames } from '../hooks/ens-cache.js';
 import SearchIndex from '../shared/search-index.js';
-import { roleIsAdminRole } from '../shared/thread-utils.js';
+import {
+  roleIsAdminRole,
+  useCommunityRootMembersToRole,
+} from '../shared/thread-utils.js';
 import type { Platform } from '../types/device-types.js';
 import {
   type CalendarQuery,
@@ -18,11 +19,9 @@
   ThreadInfo,
   RelativeMemberInfo,
   RawThreadInfo,
-  MemberInfo,
 } from '../types/minimally-encoded-thread-permissions-types.js';
 import type { BaseNavInfo } from '../types/nav-types.js';
 import type { BaseAppState } from '../types/redux-types.js';
-import { threadTypeIsCommunityRoot } from '../types/thread-types-enum.js';
 import type { UserInfo } from '../types/user-types.js';
 import { getConfig } from '../utils/config.js';
 import { values } from '../utils/objects.js';
@@ -131,22 +130,7 @@
     state => state.currentUserInfo && state.currentUserInfo.id,
   );
 
-  const communityRootMembersToRole = React.useMemo(() => {
-    const communityThreadInfos = threadInfos.filter(threadInfo =>
-      threadTypeIsCommunityRoot(threadInfo.type),
-    );
-    const communityRoots = _keyBy('id')(communityThreadInfos);
-
-    return _mapValues((threadInfo: ThreadInfo | RawThreadInfo) => {
-      const keyedMembers = _keyBy('id')(threadInfo.members);
-      const keyedMembersToRole = _mapValues(
-        (member: MemberInfo | RelativeMemberInfo) => {
-          return member.role ? threadInfo.roles[member.role] : null;
-        },
-      )(keyedMembers);
-      return keyedMembersToRole;
-    })(communityRoots);
-  }, [threadInfos]);
+  const communityRootMembersToRole = useCommunityRootMembersToRole(threadInfos);
 
   const nonViewerMembers = React.useMemo(() => {
     const allMembersOfAllThreads = new Map<string, UserInfo>();
diff --git a/lib/shared/thread-utils.js b/lib/shared/thread-utils.js
--- a/lib/shared/thread-utils.js
+++ b/lib/shared/thread-utils.js
@@ -2,6 +2,7 @@
 
 import invariant from 'invariant';
 import _find from 'lodash/fp/find.js';
+import _keyBy from 'lodash/fp/keyBy.js';
 import _mapValues from 'lodash/fp/mapValues.js';
 import _omit from 'lodash/fp/omit.js';
 import _omitBy from 'lodash/fp/omitBy.js';
@@ -116,6 +117,34 @@
   return permissionLookup(threadInfo.currentUser.permissions, permission);
 }
 
+type CommunityRootMembersToRoleType = {
+  +[threadID: ?string]: {
+    +[memberID: string]: ?RoleInfo,
+  },
+};
+function useCommunityRootMembersToRole(
+  threadInfos: $ReadOnlyArray<RawThreadInfo | ThreadInfo>,
+): CommunityRootMembersToRoleType {
+  const communityRootMembersToRole = React.useMemo(() => {
+    const communityThreadInfos = threadInfos.filter(threadInfo =>
+      threadTypeIsCommunityRoot(threadInfo.type),
+    );
+    const communityRoots = _keyBy('id')(communityThreadInfos);
+
+    return _mapValues((threadInfo: ThreadInfo) => {
+      const keyedMembers = _keyBy('id')(threadInfo.members);
+      const keyedMembersToRole = _mapValues(
+        (member: MemberInfo | RelativeMemberInfo) => {
+          return member.role ? threadInfo.roles[member.role] : null;
+        },
+      )(keyedMembers);
+      return keyedMembersToRole;
+    })(communityRoots);
+  }, [threadInfos]);
+
+  return communityRootMembersToRole;
+}
+
 function useThreadsWithPermission(
   threadInfos: $ReadOnlyArray<ThreadInfo>,
   permission: ThreadPermission,
@@ -1539,6 +1568,7 @@
 
 export {
   threadHasPermission,
+  useCommunityRootMembersToRole,
   useThreadHasPermission,
   viewerIsMember,
   threadInChatList,