diff --git a/web/modals/threads/settings/thread-settings-general-tab.react.js b/web/modals/threads/settings/thread-settings-general-tab.react.js
--- a/web/modals/threads/settings/thread-settings-general-tab.react.js
+++ b/web/modals/threads/settings/thread-settings-general-tab.react.js
@@ -3,7 +3,7 @@
 import * as React from 'react';
 import tinycolor from 'tinycolor2';
 
-import { threadHasPermission } from 'lib/shared/thread-utils.js';
+import { useThreadHasPermission } from 'lib/shared/thread-utils.js';
 import { type SetState } from 'lib/types/hook-types.js';
 import type { ThreadInfo } from 'lib/types/minimally-encoded-thread-permissions-types.js';
 import { threadPermissions } from 'lib/types/thread-permission-types.js';
@@ -80,11 +80,13 @@
     [setQueuedChanges, threadInfo.color],
   );
 
-  const threadNameInputDisabled = !threadHasPermission(
+  const canEditThreadName = useThreadHasPermission(
     threadInfo,
     threadPermissions.EDIT_THREAD_NAME,
   );
 
+  const threadNameInputDisabled = !canEditThreadName;
+
   return (
     <div className={css.container}>
       <div>
diff --git a/web/modals/threads/settings/thread-settings-modal.react.js b/web/modals/threads/settings/thread-settings-modal.react.js
--- a/web/modals/threads/settings/thread-settings-modal.react.js
+++ b/web/modals/threads/settings/thread-settings-modal.react.js
@@ -13,8 +13,8 @@
 import { getAvailableRelationshipButtons } from 'lib/shared/relationship-utils.js';
 import {
   getSingleOtherUser,
-  threadHasPermission,
   threadUIName,
+  useThreadHasPermission,
 } from 'lib/shared/thread-utils.js';
 import type { ThreadInfo } from 'lib/types/minimally-encoded-thread-permissions-types.js';
 import type { RelationshipButton } from 'lib/types/relationship-types.js';
@@ -97,43 +97,61 @@
       return getAvailableRelationshipButtons(otherUserInfo);
     }, [otherUserInfo]);
 
+    const canEditThreadName = useThreadHasPermission(
+      threadInfo,
+      threadPermissions.EDIT_THREAD_NAME,
+    );
+    const canEditThreadColor = useThreadHasPermission(
+      threadInfo,
+      threadPermissions.EDIT_THREAD_COLOR,
+    );
+    const canEditThreadDescription = useThreadHasPermission(
+      threadInfo,
+      threadPermissions.EDIT_THREAD_DESCRIPTION,
+    );
+    const canEditThreadPermissions = useThreadHasPermission(
+      threadInfo,
+      threadPermissions.EDIT_PERMISSIONS,
+    );
+    const canDeleteThread = useThreadHasPermission(
+      threadInfo,
+      threadPermissions.DELETE_THREAD,
+    );
+
     const hasPermissionForTab = React.useCallback(
       // ESLint doesn't recognize that invariant always throws
       // eslint-disable-next-line consistent-return
-      (thread: ThreadInfo, tab: TabType) => {
+      (tab: TabType) => {
         if (tab === 'general') {
           return (
-            threadHasPermission(thread, threadPermissions.EDIT_THREAD_NAME) ||
-            threadHasPermission(thread, threadPermissions.EDIT_THREAD_COLOR) ||
-            threadHasPermission(
-              thread,
-              threadPermissions.EDIT_THREAD_DESCRIPTION,
-            )
+            canEditThreadName || canEditThreadColor || canEditThreadDescription
           );
         } else if (tab === 'privacy') {
-          return threadHasPermission(
-            thread,
-            threadPermissions.EDIT_PERMISSIONS,
-          );
+          return canEditThreadPermissions;
         } else if (tab === 'delete') {
-          return threadHasPermission(thread, threadPermissions.DELETE_THREAD);
+          return canDeleteThread;
         } else if (tab === 'relationship') {
           return true;
         }
         invariant(false, `invalid tab: ${tab}`);
       },
-      [],
+      [
+        canEditThreadName,
+        canEditThreadColor,
+        canEditThreadDescription,
+        canEditThreadPermissions,
+        canDeleteThread,
+      ],
     );
 
     React.useEffect(() => {
       if (
-        threadInfo &&
         currentTabType !== 'general' &&
-        !hasPermissionForTab(threadInfo, currentTabType)
+        !hasPermissionForTab(currentTabType)
       ) {
         setCurrentTabType('general');
       }
-    }, [currentTabType, hasPermissionForTab, threadInfo]);
+    }, [currentTabType, hasPermissionForTab]);
 
     React.useEffect(() => () => setErrorMessage(''), [currentTabType]);
 
@@ -162,7 +180,7 @@
         result.push({ id: 'relationship', header: 'Relationship' });
       }
 
-      if (hasPermissionForTab(threadInfo, 'delete')) {
+      if (hasPermissionForTab('delete')) {
         result.push({ id: 'delete', header: 'Delete' });
       }