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
@@ -18,6 +18,10 @@
 import Icon from 'react-native-vector-icons/Ionicons';
 import { useDispatch } from 'react-redux';
 
+import {
+  moveDraftActionType,
+  updateDraftActionType,
+} from 'lib/actions/draft-actions';
 import {
   joinThreadActionTypes,
   joinThread,
@@ -55,7 +59,6 @@
 import Button from '../components/button.react';
 import ClearableTextInput from '../components/clearable-text-input.react';
 import SWMansionIcon from '../components/swmansion-icon.react';
-import { type UpdateDraft, type MoveDraft, useDrafts } from '../data/core-data';
 import { type InputState, InputStateContext } from '../input/input-state';
 import { getKeyboardHeight } from '../keyboard/keyboard';
 import KeyboardInputHost from '../keyboard/keyboard-input-host.react';
@@ -112,8 +115,6 @@
   // Redux state
   +viewerID: ?string,
   +draft: string,
-  +updateDraft: UpdateDraft,
-  +moveDraft: MoveDraft,
   +joinThreadLoadingStatus: LoadingStatus,
   +threadCreationInProgress: boolean,
   +calendarQuery: () => CalendarQuery,
@@ -312,10 +313,13 @@
       this.state.text &&
       this.props.threadInfo.id !== prevProps.threadInfo.id
     ) {
-      this.props.moveDraft(
-        draftKeyFromThreadID(prevProps.threadInfo.id),
-        draftKeyFromThreadID(this.props.threadInfo.id),
-      );
+      this.props.dispatch({
+        type: moveDraftActionType,
+        payload: {
+          oldKey: draftKeyFromThreadID(prevProps.threadInfo.id),
+          newKey: draftKeyFromThreadID(this.props.threadInfo.id),
+        },
+      });
     } else if (!this.state.textEdited && this.props.draft !== prevProps.draft) {
       this.setState({ text: this.props.draft });
     }
@@ -598,9 +602,12 @@
   };
 
   saveDraft = _throttle(text => {
-    this.props.updateDraft({
-      key: draftKeyFromThreadID(this.props.threadInfo.id),
-      text,
+    this.props.dispatch({
+      type: updateDraftActionType,
+      payload: {
+        key: draftKeyFromThreadID(this.props.threadInfo.id),
+        text,
+      },
     });
   }, 400);
 
@@ -830,7 +837,10 @@
   const viewerID = useSelector(
     state => state.currentUserInfo && state.currentUserInfo.id,
   );
-  const { draft, updateDraft, moveDraft } = useDrafts(props.threadInfo.id);
+  const draft = useSelector(
+    state =>
+      state.draftStore.drafts[draftKeyFromThreadID(props.threadInfo.id)] ?? '',
+  );
   const joinThreadLoadingStatus = useSelector(joinThreadLoadingStatusSelector);
   const createThreadLoadingStatus = useSelector(
     createThreadLoadingStatusSelector,
@@ -862,8 +872,6 @@
       {...props}
       viewerID={viewerID}
       draft={draft}
-      updateDraft={updateDraft}
-      moveDraft={moveDraft}
       joinThreadLoadingStatus={joinThreadLoadingStatus}
       threadCreationInProgress={threadCreationInProgress}
       calendarQuery={calendarQuery}
diff --git a/native/chat/thread-draft-updater.react.js b/native/chat/thread-draft-updater.react.js
--- a/native/chat/thread-draft-updater.react.js
+++ b/native/chat/thread-draft-updater.react.js
@@ -2,11 +2,12 @@
 
 import invariant from 'invariant';
 import * as React from 'react';
+import { useDispatch } from 'react-redux';
 
+import { moveDraftActionType } from 'lib/actions/draft-actions';
 import { pendingToRealizedThreadIDsSelector } from 'lib/selectors/thread-selectors';
 import { draftKeyFromThreadID } from 'lib/shared/thread-utils';
 
-import { useDrafts } from '../data/core-data';
 import { useSelector } from '../redux/redux-utils';
 import type { AppState } from '../redux/state-types';
 
@@ -15,7 +16,7 @@
     const pendingToRealizedThreadIDs = useSelector((state: AppState) =>
       pendingToRealizedThreadIDsSelector(state.threadStore.threadInfos),
     );
-    const drafts = useDrafts();
+    const dispatch = useDispatch();
 
     const cachedThreadIDsRef = React.useRef();
     if (!cachedThreadIDsRef.current) {
@@ -26,7 +27,6 @@
       cachedThreadIDsRef.current = newCachedThreadIDs;
     }
 
-    const { moveDraft } = drafts;
     React.useEffect(() => {
       for (const [pendingThreadID, threadID] of pendingToRealizedThreadIDs) {
         const cachedThreadIDs = cachedThreadIDsRef.current;
@@ -34,13 +34,16 @@
         if (cachedThreadIDs.has(threadID)) {
           continue;
         }
-        moveDraft(
-          draftKeyFromThreadID(pendingThreadID),
-          draftKeyFromThreadID(threadID),
-        );
+        dispatch({
+          type: moveDraftActionType,
+          payload: {
+            oldKey: draftKeyFromThreadID(pendingThreadID),
+            newKey: draftKeyFromThreadID(threadID),
+          },
+        });
         cachedThreadIDs.add(threadID);
       }
-    }, [pendingToRealizedThreadIDs, moveDraft]);
+    }, [pendingToRealizedThreadIDs, dispatch]);
     return null;
   },
 );
diff --git a/native/data/core-data-provider.react.js b/native/data/core-data-provider.react.js
deleted file mode 100644
--- a/native/data/core-data-provider.react.js
+++ /dev/null
@@ -1,157 +0,0 @@
-// @flow
-
-import * as React from 'react';
-import { useSelector } from 'react-redux';
-
-import { commCoreModule } from '../native-modules';
-import { isTaskCancelledError } from '../utils/error-handling';
-import { type CoreData, defaultCoreData, CoreDataContext } from './core-data';
-
-type Props = {
-  +children: React.Node,
-};
-function CoreDataProvider(props: Props): React.Node {
-  const [draftCache, setDraftCache] = React.useState<
-    $PropertyType<$PropertyType<CoreData, 'drafts'>, 'data'>,
-  >(defaultCoreData.drafts.data);
-
-  React.useEffect(() => {
-    (async () => {
-      try {
-        const fetchedDrafts = await commCoreModule.getAllDrafts();
-        setDraftCache(prevDrafts => {
-          const mergedDrafts = {};
-          for (const draftObj of fetchedDrafts) {
-            mergedDrafts[draftObj.key] = draftObj.text;
-          }
-          for (const key in prevDrafts) {
-            const value = prevDrafts[key];
-            if (!value) {
-              continue;
-            }
-            mergedDrafts[key] = value;
-          }
-          return mergedDrafts;
-        });
-      } catch (e) {
-        if (!isTaskCancelledError(e)) {
-          throw e;
-        }
-      }
-    })();
-  }, []);
-
-  const removeAllDrafts = React.useCallback(async () => {
-    const oldDrafts = draftCache;
-    setDraftCache({});
-    try {
-      return await commCoreModule.removeAllDrafts();
-    } catch (e) {
-      setDraftCache(oldDrafts);
-      if (!isTaskCancelledError(e)) {
-        throw e;
-      }
-    }
-  }, [draftCache]);
-
-  const viewerID = useSelector(
-    state => state.currentUserInfo && state.currentUserInfo.id,
-  );
-  const prevViewerIDRef = React.useRef();
-  React.useEffect(() => {
-    if (!viewerID) {
-      return;
-    }
-    if (prevViewerIDRef.current === viewerID) {
-      return;
-    }
-    if (prevViewerIDRef.current) {
-      removeAllDrafts();
-    }
-    prevViewerIDRef.current = viewerID;
-  }, [viewerID, removeAllDrafts]);
-
-  /**
-   * wrapper for updating the draft state receiving an array of drafts
-   *  if you want to add/update the draft, pass the draft with non-empty text
-   *  if you pass a draft with !!text == false
-   * it will remove this entry from the cache
-   */
-  const setDrafts = React.useCallback(
-    (newDrafts: $ReadOnlyArray<{ +key: string, +text: ?string }>) => {
-      setDraftCache(prevDrafts => {
-        const result = { ...prevDrafts };
-        newDrafts.forEach(draft => {
-          if (draft.text) {
-            result[draft.key] = draft.text;
-          } else {
-            delete result[draft.key];
-          }
-        });
-        return result;
-      });
-    },
-    [],
-  );
-  const updateDraft = React.useCallback(
-    async (draft: { +key: string, +text: string }) => {
-      const prevDraftText = draftCache[draft.key];
-      setDrafts([draft]);
-      try {
-        return await commCoreModule.updateDraft(draft);
-      } catch (e) {
-        setDrafts([{ key: draft.key, text: prevDraftText }]);
-        if (isTaskCancelledError(e)) {
-          return false;
-        }
-        throw e;
-      }
-    },
-    [draftCache, setDrafts],
-  );
-
-  const moveDraft = React.useCallback(
-    async (prevKey: string, newKey: string) => {
-      const value = draftCache[prevKey];
-      if (!value) {
-        return false;
-      }
-      setDrafts([
-        { key: newKey, text: value },
-        { key: prevKey, text: null },
-      ]);
-      try {
-        return await commCoreModule.moveDraft(prevKey, newKey);
-      } catch (e) {
-        setDrafts([
-          { key: newKey, text: null },
-          { key: prevKey, text: value },
-        ]);
-        if (isTaskCancelledError(e)) {
-          return false;
-        }
-        throw e;
-      }
-    },
-    [draftCache, setDrafts],
-  );
-
-  const coreData = React.useMemo(
-    () => ({
-      drafts: {
-        data: draftCache,
-        updateDraft,
-        moveDraft,
-      },
-    }),
-    [draftCache, updateDraft, moveDraft],
-  );
-
-  return (
-    <CoreDataContext.Provider value={coreData}>
-      {props.children}
-    </CoreDataContext.Provider>
-  );
-}
-
-export default CoreDataProvider;
diff --git a/native/data/core-data.js b/native/data/core-data.js
deleted file mode 100644
--- a/native/data/core-data.js
+++ /dev/null
@@ -1,75 +0,0 @@
-// @flow
-
-import * as React from 'react';
-
-import { draftKeyFromThreadID } from 'lib/shared/thread-utils';
-
-import { commCoreModule } from '../native-modules';
-import { isTaskCancelledError } from '../utils/error-handling';
-
-type DraftType = {
-  +key: string,
-  +text: string,
-};
-
-export type UpdateDraft = (draft: DraftType) => Promise<boolean>;
-export type MoveDraft = (prevKey: string, nextKey: string) => Promise<boolean>;
-
-export type CoreData = {
-  +drafts: {
-    +data: { +[key: string]: string },
-    +updateDraft: UpdateDraft,
-    +moveDraft: MoveDraft,
-  },
-};
-
-const defaultCoreData = Object.freeze({
-  drafts: {
-    data: ({}: { +[key: string]: string }),
-    updateDraft: async (draft: DraftType): Promise<boolean> => {
-      try {
-        return commCoreModule.updateDraft(draft);
-      } catch (e) {
-        if (!isTaskCancelledError(e)) {
-          throw e;
-        }
-      }
-      return false;
-    },
-    moveDraft: async (prevKey: string, nextKey: string): Promise<boolean> => {
-      try {
-        return commCoreModule.moveDraft(prevKey, nextKey);
-      } catch (e) {
-        if (!isTaskCancelledError(e)) {
-          throw e;
-        }
-      }
-      return false;
-    },
-  },
-});
-
-const CoreDataContext: React.Context<CoreData> = React.createContext<CoreData>(
-  defaultCoreData,
-);
-
-type ThreadDrafts = {
-  +draft: string,
-  +moveDraft: MoveDraft,
-  +updateDraft: UpdateDraft,
-};
-const useDrafts = (threadID: ?string): ThreadDrafts => {
-  const coreData = React.useContext(CoreDataContext);
-  return React.useMemo(
-    () => ({
-      draft: threadID
-        ? coreData.drafts.data[draftKeyFromThreadID(threadID)] ?? ''
-        : '',
-      updateDraft: coreData.drafts.updateDraft,
-      moveDraft: coreData.drafts.moveDraft,
-    }),
-    [coreData, threadID],
-  );
-};
-
-export { defaultCoreData, CoreDataContext, useDrafts };
diff --git a/native/data/sqlite-context-provider.js b/native/data/sqlite-context-provider.js
--- a/native/data/sqlite-context-provider.js
+++ b/native/data/sqlite-context-provider.js
@@ -5,6 +5,7 @@
 import ExitApp from 'react-native-exit-app';
 import { useDispatch } from 'react-redux';
 
+import { setDraftStoreDrafts } from 'lib/actions/draft-actions';
 import { setMessageStoreMessages } from 'lib/actions/message-actions.js';
 import { setThreadStoreActionType } from 'lib/actions/thread-actions';
 import { isLoggedIn } from 'lib/selectors/user-selectors';
@@ -93,9 +94,10 @@
     (async () => {
       await sensitiveDataHandled;
       try {
-        const [threads, messages] = await Promise.all([
+        const [threads, messages, drafts] = await Promise.all([
           commCoreModule.getAllThreads(),
           commCoreModule.getAllMessages(),
+          commCoreModule.getAllDrafts(),
         ]);
         const threadInfosFromDB = convertClientDBThreadInfosToRawThreadInfos(
           threads,
@@ -108,6 +110,10 @@
           type: setMessageStoreMessages,
           payload: messages,
         });
+        dispatch({
+          type: setDraftStoreDrafts,
+          payload: drafts,
+        });
         setStoreLoaded(true);
       } catch (setStoreException) {
         if (isTaskCancelledError(setStoreException)) {
diff --git a/native/root.react.js b/native/root.react.js
--- a/native/root.react.js
+++ b/native/root.react.js
@@ -22,7 +22,6 @@
 import ChatContextProvider from './chat/chat-context-provider.react';
 import PersistedStateGate from './components/persisted-state-gate';
 import ConnectedStatusBar from './connected-status-bar.react';
-import CoreDataProvider from './data/core-data-provider.react';
 import { SQLiteContextProvider } from './data/sqlite-context-provider';
 import ErrorBoundary from './error-boundary.react';
 import InputStateContainer from './input/input-state-container.react';
@@ -242,35 +241,33 @@
   return (
     <View style={styles.app}>
       <StaffContextProvider>
-        <CoreDataProvider>
-          <NavContext.Provider value={navContext}>
-            <RootContext.Provider value={rootContext}>
-              <InputStateContainer>
-                <SafeAreaProvider initialMetrics={initialWindowMetrics}>
-                  <ActionSheetProvider>
-                    <ChatContextProvider>
-                      <SQLiteContextProvider>
-                        <ConnectedStatusBar />
-                        <ReduxPersistGate persistor={getPersistor()}>
-                          {gated}
-                        </ReduxPersistGate>
-                        <PersistedStateGate>
-                          <Socket
-                            detectUnsupervisedBackgroundRef={
-                              detectUnsupervisedBackgroundRef
-                            }
-                          />
-                        </PersistedStateGate>
-                        {navigation}
-                        <NavigationHandler />
-                      </SQLiteContextProvider>
-                    </ChatContextProvider>
-                  </ActionSheetProvider>
-                </SafeAreaProvider>
-              </InputStateContainer>
-            </RootContext.Provider>
-          </NavContext.Provider>
-        </CoreDataProvider>
+        <NavContext.Provider value={navContext}>
+          <RootContext.Provider value={rootContext}>
+            <InputStateContainer>
+              <SafeAreaProvider initialMetrics={initialWindowMetrics}>
+                <ActionSheetProvider>
+                  <ChatContextProvider>
+                    <SQLiteContextProvider>
+                      <ConnectedStatusBar />
+                      <ReduxPersistGate persistor={getPersistor()}>
+                        {gated}
+                      </ReduxPersistGate>
+                      <PersistedStateGate>
+                        <Socket
+                          detectUnsupervisedBackgroundRef={
+                            detectUnsupervisedBackgroundRef
+                          }
+                        />
+                      </PersistedStateGate>
+                      {navigation}
+                      <NavigationHandler />
+                    </SQLiteContextProvider>
+                  </ChatContextProvider>
+                </ActionSheetProvider>
+              </SafeAreaProvider>
+            </InputStateContainer>
+          </RootContext.Provider>
+        </NavContext.Provider>
       </StaffContextProvider>
     </View>
   );