diff --git a/native/markdown/markdown-context-provider.react.js b/native/markdown/markdown-context-provider.react.js
--- a/native/markdown/markdown-context-provider.react.js
+++ b/native/markdown/markdown-context-provider.react.js
@@ -16,9 +16,16 @@
     [key: string]: boolean,
   }>({});
 
+  const [spoilerRevealed, setSpoilerRevealed] = React.useState<{
+    [key: string]: {
+      [key: number]: boolean,
+    },
+  }>({});
+
   const clearMarkdownContextData = React.useCallback(() => {
     setLinkModalActive({});
     setLinkPressActive({});
+    setSpoilerRevealed({});
   }, []);
 
   const contextValue = React.useMemo(
@@ -27,6 +34,8 @@
       linkModalActive,
       setLinkPressActive,
       linkPressActive,
+      setSpoilerRevealed,
+      spoilerRevealed,
       clearMarkdownContextData,
     }),
     [
@@ -34,6 +43,8 @@
       linkModalActive,
       setLinkPressActive,
       linkPressActive,
+      setSpoilerRevealed,
+      spoilerRevealed,
       clearMarkdownContextData,
     ],
   );
diff --git a/native/markdown/markdown-context.js b/native/markdown/markdown-context.js
--- a/native/markdown/markdown-context.js
+++ b/native/markdown/markdown-context.js
@@ -9,6 +9,8 @@
   +linkModalActive: { [key: string]: boolean },
   +setLinkPressActive: SetState<{ [key: string]: boolean }>,
   +linkPressActive: { [key: string]: boolean },
+  +setSpoilerRevealed: SetState<{ [key: string]: { [key: number]: boolean } }>,
+  +spoilerRevealed: { [key: string]: { [key: number]: boolean } },
   +clearMarkdownContextData: () => void,
 };
 
diff --git a/native/markdown/markdown-spoiler.react.js b/native/markdown/markdown-spoiler.react.js
--- a/native/markdown/markdown-spoiler.react.js
+++ b/native/markdown/markdown-spoiler.react.js
@@ -5,32 +5,77 @@
 
 import type { ReactElement } from 'lib/shared/markdown';
 
+import { MessageContext } from '../chat/message-context.react';
+import GestureTouchableOpacity from '../components/gesture-touchable-opacity.react';
 import { useStyles } from '../themes/colors';
+import { MarkdownContext } from './markdown-context';
 
 type MarkdownSpoilerProps = {
+  +spoilerIdentifier: string | number | void,
   +text: ReactElement,
   +children?: React.Node,
 };
 
 function MarkdownSpoiler(props: MarkdownSpoilerProps): React.Node {
-  const [isRevealed, setIsRevealed] = React.useState(false);
+  const markdownContext = React.useContext(MarkdownContext);
+  const messageContext = React.useContext(MessageContext);
   const styles = useStyles(unboundStyles);
-  const { text } = props;
+
+  const { messageID } = messageContext;
+  const { text, spoilerIdentifier } = props;
+
+  const setSpoilerRevealed = markdownContext?.setSpoilerRevealed;
+  const spoilerRevealed = markdownContext?.spoilerRevealed;
+  const parsedSpoilerIdentifier = spoilerIdentifier
+    ? parseInt(spoilerIdentifier)
+    : -1;
+
+  const isRevealed = React.useMemo(
+    () => spoilerRevealed?.[messageID]?.[parsedSpoilerIdentifier] ?? false,
+    [spoilerRevealed, messageID, parsedSpoilerIdentifier],
+  );
+
+  const styleBasedOnSpoilerState = React.useMemo(() => {
+    if (isRevealed) {
+      return null;
+    }
+    return styles.spoilerHidden;
+  }, [isRevealed, styles.spoilerHidden]);
 
   const onSpoilerClick = React.useCallback(() => {
-    setIsRevealed(true);
-  }, []);
+    if (isRevealed) {
+      return;
+    }
+
+    if (
+      spoilerRevealed &&
+      setSpoilerRevealed &&
+      messageID &&
+      parsedSpoilerIdentifier
+    ) {
+      setSpoilerRevealed({
+        ...spoilerRevealed,
+        [messageID]: {
+          ...spoilerRevealed[messageID],
+          [parsedSpoilerIdentifier]: true,
+        },
+      });
+    }
+  }, [
+    isRevealed,
+    spoilerRevealed,
+    setSpoilerRevealed,
+    messageID,
+    parsedSpoilerIdentifier,
+  ]);
 
   const memoizedSpoiler = React.useMemo(() => {
     return (
-      <Text
-        onPress={onSpoilerClick}
-        style={!isRevealed ? styles.spoilerHidden : null}
-      >
-        {text}
-      </Text>
+      <GestureTouchableOpacity onPress={onSpoilerClick}>
+        <Text style={styleBasedOnSpoilerState}>{text}</Text>
+      </GestureTouchableOpacity>
     );
-  }, [onSpoilerClick, isRevealed, styles.spoilerHidden, text]);
+  }, [onSpoilerClick, styleBasedOnSpoilerState, text]);
 
   return memoizedSpoiler;
 }
diff --git a/native/markdown/rules.react.js b/native/markdown/rules.react.js
--- a/native/markdown/rules.react.js
+++ b/native/markdown/rules.react.js
@@ -200,7 +200,11 @@
         output: SharedMarkdown.Output<SharedMarkdown.ReactElement>,
         state: SharedMarkdown.State,
       ) => (
-        <MarkdownSpoiler key={state.key} text={output(node.content, state)} />
+        <MarkdownSpoiler
+          key={state.key}
+          spoilerIdentifier={state.key}
+          text={output(node.content, state)}
+        />
       ),
     },
     inlineCode: {