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
@@ -268,7 +268,12 @@
   +openCamera: () => mixed,
   +navigation?: ChatNavigationProp<'MessageList'>,
 };
-function ConnectedChatInputBarBase(props: ConnectedChatInputBarBaseProps) {
+function ConnectedChatInputBarBase({
+  threadInfo,
+  navigation,
+  openCamera,
+  onInputBarLayout,
+}: ConnectedChatInputBarBaseProps) {
   const navContext = React.useContext(NavContext);
   const keyboardState = React.useContext(KeyboardContext);
   const inputState = React.useContext(InputStateContext);
@@ -278,8 +283,7 @@
     state => state.currentUserInfo && state.currentUserInfo.id,
   );
   const draft = useSelector(
-    state =>
-      state.draftStore.drafts[draftKeyFromThreadID(props.threadInfo.id)] ?? '',
+    state => state.draftStore.drafts[draftKeyFromThreadID(threadInfo.id)] ?? '',
   );
   const joinThreadLoadingStatus = useSelector(joinThreadLoadingStatusSelector);
   const createThreadLoadingStatus = useSelector(
@@ -298,20 +302,20 @@
   const colors = useColors();
 
   const isActive = React.useMemo(
-    () => props.threadInfo.id === activeThreadSelector(navContext),
-    [props.threadInfo.id, navContext],
+    () => threadInfo.id === activeThreadSelector(navContext),
+    [threadInfo.id, navContext],
   );
 
   const dispatch = useDispatch();
   const dispatchActionPromise = useDispatchActionPromise();
   const rawThreadInfo = useSelector(
-    state => state.threadStore.threadInfos[props.threadInfo.id],
+    state => state.threadStore.threadInfos[threadInfo.id],
   );
 
   const { getChatMentionSearchIndex } = useChatMentionContext();
-  const chatMentionSearchIndex = getChatMentionSearchIndex(props.threadInfo);
+  const chatMentionSearchIndex = getChatMentionSearchIndex(threadInfo);
 
-  const { parentThreadID, community } = props.threadInfo;
+  const { parentThreadID, community } = threadInfo;
   const parentThreadInfo = useSelector(state =>
     parentThreadID ? threadInfoSelector(state)[parentThreadID] : null,
   );
@@ -320,30 +324,28 @@
   );
 
   const threadFrozen = useThreadFrozenDueToViewerBlock(
-    props.threadInfo,
+    threadInfo,
     communityThreadInfo,
     viewerID,
     userInfos,
   );
 
   const userMentionsCandidates = useUserMentionsCandidates(
-    props.threadInfo,
+    threadInfo,
     parentThreadInfo,
   );
 
-  const chatMentionCandidates = useThreadChatMentionCandidates(
-    props.threadInfo,
-  );
+  const chatMentionCandidates = useThreadChatMentionCandidates(threadInfo);
 
   const messageEditingContext = React.useContext(MessageEditingContext);
 
   const editedMessageInfo = messageEditingContext?.editState.editedMessage;
   const editedMessagePreview = useMessagePreview(
     editedMessageInfo,
-    props.threadInfo,
+    threadInfo,
     getDefaultTextMessageRules(chatMentionCandidates).simpleMarkdownRules,
   );
-  const editMessage = useEditMessage(props.threadInfo);
+  const editMessage = useEditMessage(threadInfo);
 
   const [selectionState, setSelectionState] =
     React.useState<SyncedSelectionData>({
@@ -394,12 +396,12 @@
     );
 
   const currentUserIsVoiced = useThreadHasPermission(
-    props.threadInfo,
+    threadInfo,
     threadPermissions.VOICED,
   );
 
   const currentUserCanJoin = useThreadHasPermission(
-    props.threadInfo,
+    threadInfo,
     threadPermissions.JOIN_THREAD,
   );
 
@@ -542,15 +544,14 @@
     if (!threadCreationInProgress) {
       return false;
     }
-    return checkIfDefaultMembersAreVoiced(props.threadInfo);
-  }, [currentUserIsVoiced, props.threadInfo, threadCreationInProgress]);
+    return checkIfDefaultMembersAreVoiced(threadInfo);
+  }, [currentUserIsVoiced, threadInfo, threadCreationInProgress]);
 
   const isEditMode = React.useCallback(() => {
     const editState = messageEditingContext?.editState;
-    const isThisThread =
-      editState?.editedMessage?.threadID === props.threadInfo.id;
+    const isThisThread = editState?.editedMessage?.threadID === threadInfo.id;
     return editState?.editedMessage !== null && isThisThread;
-  }, [messageEditingContext?.editState, props.threadInfo.id]);
+  }, [messageEditingContext?.editState, threadInfo.id]);
 
   const immediatelyShowSendButton = React.useCallback(() => {
     sendButtonContainerOpen.setValue(1);
@@ -626,12 +627,12 @@
         dispatch({
           type: updateDraftActionType,
           payload: {
-            key: draftKeyFromThreadID(props.threadInfo.id),
+            key: draftKeyFromThreadID(threadInfo.id),
             text: newText,
           },
         });
       }, 400),
-    [dispatch, props.threadInfo.id],
+    [dispatch, threadInfo.id],
   );
 
   const isMessageEdited = React.useCallback(
@@ -673,16 +674,11 @@
   }, [immediatelyHideButtons, immediatelyShowSendButton]);
 
   const unblockNavigation = React.useCallback(() => {
-    const { navigation } = props;
-    if (!navigation) {
-      return;
-    }
-    navigation.setParams({ removeEditMode: null });
-  }, [props]);
+    navigation?.setParams({ removeEditMode: null });
+  }, [navigation]);
 
   const removeEditMode: RemoveEditMode = React.useCallback(
     action => {
-      const { navigation } = props;
       if (!navigation || isExitingDuringEditModeRef.current) {
         return 'ignore_action';
       }
@@ -703,18 +699,17 @@
       });
       return 'ignore_action';
     },
-    [isMessageEdited, overlayContext, props, unblockNavigation],
+    [isMessageEdited, navigation, overlayContext, unblockNavigation],
   );
 
   const blockNavigation = React.useCallback(() => {
-    const { navigation } = props;
     if (!navigation || !navigation.isFocused()) {
       return;
     }
     navigation.setParams({
       removeEditMode: removeEditMode,
     });
-  }, [props, removeEditMode]);
+  }, [navigation, removeEditMode]);
 
   const exitEditMode = React.useCallback(() => {
     messageEditingContext?.setEditedMessage(null, () => {
@@ -842,12 +837,12 @@
       {
         type: messageTypes.TEXT,
         localID,
-        threadID: props.threadInfo.id,
+        threadID: threadInfo.id,
         text: newText,
         creatorID,
         time: Date.now(),
       },
-      props.threadInfo,
+      threadInfo,
       parentThreadInfo,
     );
   }, [
@@ -855,7 +850,7 @@
     getEditedMessage,
     inputState,
     parentThreadInfo,
-    props.threadInfo,
+    threadInfo,
     text,
     updateSendButton,
     viewerID,
@@ -907,7 +902,7 @@
       const saveExit = () => {
         messageEditingContext?.setEditedMessage(null, () => {
           isExitingDuringEditModeRef.current = true;
-          props.navigation?.dispatch(action);
+          navigation?.dispatch(action);
         });
       };
       if (!isMessageEdited()) {
@@ -918,7 +913,7 @@
         onDiscard: saveExit,
       });
     },
-    [isEditMode, isMessageEdited, messageEditingContext, props.navigation],
+    [isEditMode, isMessageEdited, messageEditingContext, navigation],
   );
 
   React.useEffect(() => {
@@ -934,8 +929,6 @@
   }, [addEditInputMessageListener, isActive, removeEditInputMessageListener]);
 
   React.useEffect(() => {
-    const { navigation } = props;
-
     const clearBeforeRemoveListener = navigation?.addListener(
       'beforeRemove',
       onNavigationBeforeRemove,
@@ -950,7 +943,12 @@
       clearFocusListener?.();
       clearBlurListener?.();
     };
-  }, [onNavigationBeforeRemove, onNavigationBlur, onNavigationFocus, props]);
+  }, [
+    navigation,
+    onNavigationBeforeRemove,
+    onNavigationBlur,
+    onNavigationFocus,
+  ]);
 
   const callJoinThread = useJoinThread();
 
@@ -965,20 +963,20 @@
       const query = calendarQuery();
       joinThreadInput = {
         thick: false,
-        threadID: props.threadInfo.id,
+        threadID: threadInfo.id,
         calendarQuery: {
           startDate: query.startDate,
           endDate: query.endDate,
           filters: [
             ...query.filters,
-            { type: 'threads', threadIDs: [props.threadInfo.id] },
+            { type: 'threads', threadIDs: [threadInfo.id] },
           ],
         },
       };
     }
 
     return await callJoinThread(joinThreadInput);
-  }, [calendarQuery, callJoinThread, props.threadInfo.id, rawThreadInfo]);
+  }, [calendarQuery, callJoinThread, threadInfo.id, rawThreadInfo]);
 
   const onPressJoin = React.useCallback(() => {
     void dispatchActionPromise(joinThreadActionTypes, joinAction());
@@ -1001,8 +999,8 @@
 
   const showMediaGallery = React.useCallback(() => {
     invariant(keyboardState, 'keyboardState should be initialized');
-    keyboardState.showMediaGallery(props.threadInfo);
-  }, [keyboardState, props.threadInfo]);
+    keyboardState.showMediaGallery(threadInfo);
+  }, [keyboardState, threadInfo]);
 
   const dismissKeyboard = React.useCallback(() => {
     keyboardState?.dismissKeyboard();
@@ -1016,21 +1014,21 @@
       textEdited &&
       text &&
       prevThreadInfoID.current &&
-      props.threadInfo.id !== prevThreadInfoID.current
+      threadInfo.id !== prevThreadInfoID.current
     ) {
       dispatch({
         type: moveDraftActionType,
         payload: {
           oldKey: draftKeyFromThreadID(prevThreadInfoID.current),
-          newKey: draftKeyFromThreadID(props.threadInfo.id),
+          newKey: draftKeyFromThreadID(threadInfo.id),
         },
       });
     } else if (!textEdited && draft !== prevDraft.current) {
       setText(draft);
     }
-    prevThreadInfoID.current = props.threadInfo.id;
+    prevThreadInfoID.current = threadInfo.id;
     prevDraft.current = draft;
-  }, [dispatch, draft, props.threadInfo.id, text, textEdited]);
+  }, [dispatch, draft, threadInfo.id, text, textEdited]);
 
   const prevIsActiveRef = React.useRef(isActive);
   React.useEffect(() => {
@@ -1104,12 +1102,12 @@
           <SWMansionIcon
             name="chevron-right"
             size={22}
-            color={`#${props.threadInfo.color}`}
+            color={`#${threadInfo.color}`}
           />
         </AnimatedView>
       </TouchableOpacity>
     );
-    const threadColor = `#${props.threadInfo.color}`;
+    const threadColor = `#${threadInfo.color}`;
     const expandoButtonsViewStyle: Array<ViewStyle> = [
       styles.innerExpandoButtons,
     ];
@@ -1127,12 +1125,12 @@
                   <SWMansionIcon
                     name="image-1"
                     size={28}
-                    color={`#${props.threadInfo.color}`}
+                    color={`#${threadInfo.color}`}
                   />
                 </AnimatedView>
               </TouchableOpacity>
               <TouchableOpacity
-                onPress={props.openCamera}
+                onPress={openCamera}
                 activeOpacity={0.4}
                 disabled={!buttonsExpanded}
               >
@@ -1140,7 +1138,7 @@
                   <SWMansionIcon
                     name="camera"
                     size={28}
-                    color={`#${props.threadInfo.color}`}
+                    color={`#${threadInfo.color}`}
                   />
                 </AnimatedView>
               </TouchableOpacity>
@@ -1148,7 +1146,7 @@
             </View>
           </AnimatedView>
           <SelectableTextInput
-            allowImagePasteForThreadID={props.threadInfo.id}
+            allowImagePasteForThreadID={threadInfo.id}
             value={text}
             onChangeText={updateText}
             selection={selectionState.selection}
@@ -1160,7 +1158,7 @@
             textInputRef={setTextInputRef}
             clearableTextInputRef={setClearableTextInputRef}
             ref={selectableTextInputRef}
-            selectionColor={`#${props.threadInfo.color}`}
+            selectionColor={`#${threadInfo.color}`}
           />
           <AnimatedView style={sendButtonContainerStyle}>
             <TouchableOpacity
@@ -1182,9 +1180,9 @@
     );
   };
 
-  const isMember = viewerIsMember(props.threadInfo);
+  const isMember = viewerIsMember(threadInfo);
   let joinButton = null;
-  const threadColor = `#${props.threadInfo.color}`;
+  const threadColor = `#${threadInfo.color}`;
 
   if (!isMember && currentUserCanJoin && !threadCreationInProgress) {
     let buttonContent;
@@ -1197,7 +1195,7 @@
         />
       );
     } else {
-      const textStyle = colorIsDark(props.threadInfo.color)
+      const textStyle = colorIsDark(threadInfo.color)
         ? styles.joinButtonTextLight
         : styles.joinButtonTextDark;
       buttonContent = (
@@ -1236,14 +1234,12 @@
   }
 
   let content;
-  const defaultMembersAreVoiced = checkIfDefaultMembersAreVoiced(
-    props.threadInfo,
-  );
+  const defaultMembersAreVoiced = checkIfDefaultMembersAreVoiced(threadInfo);
   if (shouldShowTextInput()) {
     content = renderInput();
   } else if (
     threadFrozen &&
-    threadActualMembers(props.threadInfo.members).length === 2
+    threadActualMembers(threadInfo.members).length === 2
   ) {
     content = (
       <Text style={styles.explanation}>
@@ -1302,7 +1298,7 @@
   }
 
   return (
-    <AnimatedView style={styles.container} onLayout={props.onInputBarLayout}>
+    <AnimatedView style={styles.container} onLayout={onInputBarLayout}>
       {typeaheadTooltip}
       {joinButton}
       {editedMessage}