diff --git a/experiments-app/src/experiments.ts b/experiments-app/src/experiments.ts
index fdd485148..af889cfb1 100644
--- a/experiments-app/src/experiments.ts
+++ b/experiments-app/src/experiments.ts
@@ -1,4 +1,5 @@
 import { AccessibilityScreen } from './screens/Accessibility';
+import { PressEvents } from './screens/PressEvents';
 import { TextInputEventPropagation } from './screens/TextInputEventPropagation';
 import { TextInputEvents } from './screens/TextInputEvents';
 import { ScrollViewEvents } from './screens/ScrollViewEvents';
@@ -13,6 +14,11 @@ export const experiments = [
     title: 'Accessibility',
     component: AccessibilityScreen,
   },
+  {
+    key: 'PressEvents',
+    title: 'Press Events',
+    component: PressEvents,
+  },
   {
     key: 'TextInputEvents',
     title: 'TextInput Events',
diff --git a/experiments-app/src/screens/PressEvents.tsx b/experiments-app/src/screens/PressEvents.tsx
new file mode 100644
index 000000000..a8ba3edcc
--- /dev/null
+++ b/experiments-app/src/screens/PressEvents.tsx
@@ -0,0 +1,82 @@
+import * as React from 'react';
+import {
+  StyleSheet,
+  SafeAreaView,
+  Text,
+  TextInput,
+  View,
+  Pressable,
+  TouchableOpacity,
+} from 'react-native';
+import { nativeEventLogger, logEvent } from '../utils/helpers';
+
+export function PressEvents() {
+  const [value, setValue] = React.useState('');
+
+  const handleChangeText = (value: string) => {
+    setValue(value);
+    logEvent('changeText', value);
+  };
+
+  return (
+    <SafeAreaView style={styles.container}>
+      <View style={styles.wrapper}>
+        <TextInput
+          style={styles.textInput}
+          value={value}
+          onPress={nativeEventLogger('press')}
+          onPressIn={nativeEventLogger('pressIn')}
+          onPressOut={nativeEventLogger('pressOut')}
+        />
+      </View>
+      <View style={styles.wrapper}>
+        <Text
+          onPress={nativeEventLogger('press')}
+          onLongPress={nativeEventLogger('longPress')}
+          onPressIn={nativeEventLogger('pressIn')}
+          onPressOut={nativeEventLogger('pressOut')}
+        >
+          Text
+        </Text>
+      </View>
+      <View style={styles.wrapper}>
+        <Pressable
+          onPress={nativeEventLogger('press')}
+          onLongPress={nativeEventLogger('longPress')}
+          onPressIn={nativeEventLogger('pressIn')}
+          onPressOut={nativeEventLogger('pressOut')}
+        >
+          <Text>Pressable</Text>
+        </Pressable>
+      </View>
+      <View style={styles.wrapper}>
+        <TouchableOpacity
+          onPress={nativeEventLogger('press')}
+          onLongPress={nativeEventLogger('longPress')}
+          onPressIn={nativeEventLogger('pressIn')}
+          onPressOut={nativeEventLogger('pressOut')}
+        >
+          <Text>Pressable</Text>
+        </TouchableOpacity>
+      </View>
+    </SafeAreaView>
+  );
+}
+
+const styles = StyleSheet.create({
+  container: {
+    flex: 1,
+  },
+  wrapper: {
+    padding: 20,
+    backgroundColor: 'yellow',
+  },
+  textInput: {
+    backgroundColor: 'white',
+    margin: 20,
+    padding: 8,
+    fontSize: 18,
+    borderWidth: 1,
+    borderColor: 'grey',
+  },
+});
diff --git a/experiments-app/src/utils/helpers.ts b/experiments-app/src/utils/helpers.ts
index 5993a46c4..1366177b7 100644
--- a/experiments-app/src/utils/helpers.ts
+++ b/experiments-app/src/utils/helpers.ts
@@ -1,5 +1,7 @@
 import { NativeSyntheticEvent } from 'react-native/types';
 
+let lastEventTimeStamp: number | null = null;
+
 export function nativeEventLogger(name: string) {
   return (event: NativeSyntheticEvent<unknown>) => {
     logEvent(name, event?.nativeEvent);
@@ -14,5 +16,6 @@ export function customEventLogger(name: string) {
 
 export function logEvent(name: string, ...args: unknown[]) {
   // eslint-disable-next-line no-console
-  console.log(`Event: ${name}`, ...args);
+  console.log(`[${Date.now() - (lastEventTimeStamp ?? Date.now())}ms] Event: ${name}`, ...args);
+  lastEventTimeStamp = Date.now();
 }
diff --git a/src/__tests__/render.test.tsx b/src/__tests__/render.test.tsx
index 3127963d7..fae79012b 100644
--- a/src/__tests__/render.test.tsx
+++ b/src/__tests__/render.test.tsx
@@ -249,5 +249,5 @@ test('supports legacy rendering', () => {
 
 test('supports concurrent rendering', () => {
   render(<View testID="test" />, { concurrentRoot: true });
-  expect(screen.root).toBeDefined();
+  expect(screen.root).toBeOnTheScreen();
 });
diff --git a/src/fire-event.ts b/src/fire-event.ts
index 98c7745a3..0f0287f5e 100644
--- a/src/fire-event.ts
+++ b/src/fire-event.ts
@@ -7,7 +7,7 @@ import {
   ScrollViewProps,
 } from 'react-native';
 import act from './act';
-import { isHostElement } from './helpers/component-tree';
+import { isElementMounted, isHostElement } from './helpers/component-tree';
 import { isHostScrollView, isHostTextInput } from './helpers/host-component-names';
 import { isPointerEventEnabled } from './helpers/pointer-events';
 import { isTextInputEditable } from './helpers/text-input';
@@ -121,6 +121,10 @@ type EventName = StringWithAutocomplete<
 >;
 
 function fireEvent(element: ReactTestInstance, eventName: EventName, ...data: unknown[]) {
+  if (!isElementMounted(element)) {
+    return;
+  }
+
   setNativeStateIfNeeded(element, eventName, data[0]);
 
   const handler = findEventHandler(element, eventName);
diff --git a/src/helpers/component-tree.ts b/src/helpers/component-tree.ts
index 8387278b5..4a4a00897 100644
--- a/src/helpers/component-tree.ts
+++ b/src/helpers/component-tree.ts
@@ -1,5 +1,5 @@
 import { ReactTestInstance } from 'react-test-renderer';
-
+import { screen } from '../screen';
 /**
  * ReactTestInstance referring to host element.
  */
@@ -13,6 +13,10 @@ export function isHostElement(element?: ReactTestInstance | null): element is Ho
   return typeof element?.type === 'string';
 }
 
+export function isElementMounted(element: ReactTestInstance | null) {
+  return getUnsafeRootElement(element) === screen.UNSAFE_root;
+}
+
 /**
  * Returns first host ancestor for given element.
  * @param element The element start traversing from.
diff --git a/src/user-event/press/__tests__/__snapshots__/longPress.test.tsx.snap b/src/user-event/press/__tests__/__snapshots__/longPress.test.tsx.snap
index fa31b7a34..b1c8a3fb2 100644
--- a/src/user-event/press/__tests__/__snapshots__/longPress.test.tsx.snap
+++ b/src/user-event/press/__tests__/__snapshots__/longPress.test.tsx.snap
@@ -34,3 +34,98 @@ exports[`userEvent.longPress with fake timers calls onLongPress if the delayLong
   },
 ]
 `;
+
+exports[`userEvent.longPress with fake timers works on Pressable 1`] = `
+[
+  {
+    "name": "pressIn",
+    "payload": {
+      "currentTarget": {
+        "measure": [Function],
+      },
+      "dispatchConfig": {
+        "registrationName": "onResponderGrant",
+      },
+      "isDefaultPrevented": [Function],
+      "isPersistent": [Function],
+      "isPropagationStopped": [Function],
+      "nativeEvent": {
+        "changedTouches": [],
+        "identifier": 0,
+        "locationX": 0,
+        "locationY": 0,
+        "pageX": 0,
+        "pageY": 0,
+        "target": 0,
+        "timestamp": 0,
+        "touches": [],
+      },
+      "persist": [Function],
+      "preventDefault": [Function],
+      "stopPropagation": [Function],
+      "target": {},
+      "timeStamp": 0,
+    },
+  },
+  {
+    "name": "longPress",
+    "payload": {
+      "currentTarget": {
+        "measure": [Function],
+      },
+      "dispatchConfig": {
+        "registrationName": "onResponderGrant",
+      },
+      "isDefaultPrevented": [Function],
+      "isPersistent": [Function],
+      "isPropagationStopped": [Function],
+      "nativeEvent": {
+        "changedTouches": [],
+        "identifier": 0,
+        "locationX": 0,
+        "locationY": 0,
+        "pageX": 0,
+        "pageY": 0,
+        "target": 0,
+        "timestamp": 0,
+        "touches": [],
+      },
+      "persist": [Function],
+      "preventDefault": [Function],
+      "stopPropagation": [Function],
+      "target": {},
+      "timeStamp": 0,
+    },
+  },
+  {
+    "name": "pressOut",
+    "payload": {
+      "currentTarget": {
+        "measure": [Function],
+      },
+      "dispatchConfig": {
+        "registrationName": "onResponderRelease",
+      },
+      "isDefaultPrevented": [Function],
+      "isPersistent": [Function],
+      "isPropagationStopped": [Function],
+      "nativeEvent": {
+        "changedTouches": [],
+        "identifier": 0,
+        "locationX": 0,
+        "locationY": 0,
+        "pageX": 0,
+        "pageY": 0,
+        "target": 0,
+        "timestamp": 500,
+        "touches": [],
+      },
+      "persist": [Function],
+      "preventDefault": [Function],
+      "stopPropagation": [Function],
+      "target": {},
+      "timeStamp": 0,
+    },
+  },
+]
+`;
diff --git a/src/user-event/press/__tests__/__snapshots__/press.test.tsx.snap b/src/user-event/press/__tests__/__snapshots__/press.test.tsx.snap
index ceb2803f3..d4dc3df36 100644
--- a/src/user-event/press/__tests__/__snapshots__/press.test.tsx.snap
+++ b/src/user-event/press/__tests__/__snapshots__/press.test.tsx.snap
@@ -1,6 +1,6 @@
 // Jest Snapshot v1, https://goo.gl/fbAQLP
 
-exports[`userEvent.press with fake timers calls onPressIn, onPress and onPressOut prop of touchable 1`] = `
+exports[`userEvent.press with fake timers works on Pressable 1`] = `
 [
   {
     "name": "pressIn",
@@ -33,7 +33,7 @@ exports[`userEvent.press with fake timers calls onPressIn, onPress and onPressOu
     },
   },
   {
-    "name": "press",
+    "name": "pressOut",
     "payload": {
       "currentTarget": {
         "measure": [Function],
@@ -52,7 +52,7 @@ exports[`userEvent.press with fake timers calls onPressIn, onPress and onPressOu
         "pageX": 0,
         "pageY": 0,
         "target": 0,
-        "timestamp": 0,
+        "timestamp": 130,
         "touches": [],
       },
       "persist": [Function],
@@ -63,7 +63,7 @@ exports[`userEvent.press with fake timers calls onPressIn, onPress and onPressOu
     },
   },
   {
-    "name": "pressOut",
+    "name": "press",
     "payload": {
       "currentTarget": {
         "measure": [Function],
@@ -82,7 +82,7 @@ exports[`userEvent.press with fake timers calls onPressIn, onPress and onPressOu
         "pageX": 0,
         "pageY": 0,
         "target": 0,
-        "timestamp": 0,
+        "timestamp": 130,
         "touches": [],
       },
       "persist": [Function],
diff --git a/src/user-event/press/__tests__/longPress.real-timers.test.tsx b/src/user-event/press/__tests__/longPress.real-timers.test.tsx
index 928e5b6d3..4c693830c 100644
--- a/src/user-event/press/__tests__/longPress.real-timers.test.tsx
+++ b/src/user-event/press/__tests__/longPress.real-timers.test.tsx
@@ -1,6 +1,7 @@
 import React from 'react';
-import { Pressable, Text } from 'react-native';
-import { render, screen } from '../../../pure';
+import { Pressable, Text, TouchableHighlight, TouchableOpacity } from 'react-native';
+import { createEventLogger, getEventsNames } from '../../../test-utils';
+import { render, screen } from '../../..';
 import { userEvent } from '../..';
 
 describe('userEvent.longPress with real timers', () => {
@@ -9,6 +10,68 @@ describe('userEvent.longPress with real timers', () => {
     jest.restoreAllMocks();
   });
 
+  test('works on Pressable', async () => {
+    const { events, logEvent } = createEventLogger();
+    const user = userEvent.setup();
+
+    render(
+      <Pressable
+        onPress={logEvent('press')}
+        onPressIn={logEvent('pressIn')}
+        onPressOut={logEvent('pressOut')}
+        onLongPress={logEvent('longPress')}
+        testID="pressable"
+      />,
+    );
+
+    await user.longPress(screen.getByTestId('pressable'));
+    expect(getEventsNames(events)).toEqual(['pressIn', 'longPress', 'pressOut']);
+  });
+
+  test('works on TouchableOpacity', async () => {
+    const mockOnPress = jest.fn();
+
+    render(
+      <TouchableOpacity onPress={mockOnPress}>
+        <Text>press me</Text>
+      </TouchableOpacity>,
+    );
+
+    await userEvent.longPress(screen.getByText('press me'));
+    expect(mockOnPress).toHaveBeenCalled();
+  });
+
+  test('works on TouchableHighlight', async () => {
+    const mockOnPress = jest.fn();
+
+    render(
+      <TouchableHighlight onPress={mockOnPress}>
+        <Text>press me</Text>
+      </TouchableHighlight>,
+    );
+
+    await userEvent.longPress(screen.getByText('press me'));
+    expect(mockOnPress).toHaveBeenCalled();
+  });
+
+  test('works on Text', async () => {
+    const { events, logEvent } = createEventLogger();
+
+    render(
+      <Text
+        onPress={logEvent('press')}
+        onPressIn={logEvent('pressIn')}
+        onPressOut={logEvent('pressOut')}
+        onLongPress={logEvent('longPress')}
+      >
+        press me
+      </Text>,
+    );
+
+    await userEvent.longPress(screen.getByText('press me'));
+    expect(getEventsNames(events)).toEqual(['pressIn', 'longPress', 'pressOut']);
+  });
+
   test('calls onLongPress if the delayLongPress is the default one', async () => {
     const mockOnLongPress = jest.fn();
     const user = userEvent.setup();
diff --git a/src/user-event/press/__tests__/longPress.test.tsx b/src/user-event/press/__tests__/longPress.test.tsx
index 3716446e7..bbf5d0582 100644
--- a/src/user-event/press/__tests__/longPress.test.tsx
+++ b/src/user-event/press/__tests__/longPress.test.tsx
@@ -1,8 +1,8 @@
 import React from 'react';
-import { Pressable, Text } from 'react-native';
-import { render, screen } from '../../../pure';
+import { Pressable, Text, TouchableHighlight, TouchableOpacity } from 'react-native';
+import { createEventLogger, getEventsNames } from '../../../test-utils';
+import { render, screen } from '../../..';
 import { userEvent } from '../..';
-import { createEventLogger } from '../../../test-utils';
 
 describe('userEvent.longPress with fake timers', () => {
   beforeEach(() => {
@@ -10,6 +10,69 @@ describe('userEvent.longPress with fake timers', () => {
     jest.setSystemTime(0);
   });
 
+  test('works on Pressable', async () => {
+    const { events, logEvent } = createEventLogger();
+    const user = userEvent.setup();
+
+    render(
+      <Pressable
+        onPress={logEvent('press')}
+        onPressIn={logEvent('pressIn')}
+        onPressOut={logEvent('pressOut')}
+        onLongPress={logEvent('longPress')}
+        testID="pressable"
+      />,
+    );
+
+    await user.longPress(screen.getByTestId('pressable'));
+    expect(getEventsNames(events)).toEqual(['pressIn', 'longPress', 'pressOut']);
+    expect(events).toMatchSnapshot();
+  });
+
+  test('works on TouchableOpacity', async () => {
+    const mockOnPress = jest.fn();
+
+    render(
+      <TouchableOpacity onPress={mockOnPress}>
+        <Text>press me</Text>
+      </TouchableOpacity>,
+    );
+
+    await userEvent.longPress(screen.getByText('press me'));
+    expect(mockOnPress).toHaveBeenCalled();
+  });
+
+  test('works on TouchableHighlight', async () => {
+    const mockOnPress = jest.fn();
+
+    render(
+      <TouchableHighlight onPress={mockOnPress}>
+        <Text>press me</Text>
+      </TouchableHighlight>,
+    );
+
+    await userEvent.longPress(screen.getByText('press me'));
+    expect(mockOnPress).toHaveBeenCalled();
+  });
+
+  test('works on Text', async () => {
+    const { events, logEvent } = createEventLogger();
+
+    render(
+      <Text
+        onPress={logEvent('press')}
+        onPressIn={logEvent('pressIn')}
+        onPressOut={logEvent('pressOut')}
+        onLongPress={logEvent('longPress')}
+      >
+        press me
+      </Text>,
+    );
+
+    await userEvent.longPress(screen.getByText('press me'));
+    expect(getEventsNames(events)).toEqual(['pressIn', 'longPress', 'pressOut']);
+  });
+
   test('calls onLongPress if the delayLongPress is the default one', async () => {
     const { logEvent, events } = createEventLogger();
     const user = userEvent.setup();
diff --git a/src/user-event/press/__tests__/press.real-timers.test.tsx b/src/user-event/press/__tests__/press.real-timers.test.tsx
index 1ba53c27e..042b9eded 100644
--- a/src/user-event/press/__tests__/press.real-timers.test.tsx
+++ b/src/user-event/press/__tests__/press.real-timers.test.tsx
@@ -1,5 +1,6 @@
 import * as React from 'react';
 import {
+  Button,
   Pressable,
   Text,
   TextInput,
@@ -17,7 +18,7 @@ describe('userEvent.press with real timers', () => {
     jest.restoreAllMocks();
   });
 
-  test('calls onPressIn, onPress and onPressOut prop of touchable', async () => {
+  test('works on Pressable', async () => {
     const { events, logEvent } = createEventLogger();
     const user = userEvent.setup();
 
@@ -30,9 +31,77 @@ describe('userEvent.press with real timers', () => {
         testID="pressable"
       />,
     );
+
     await user.press(screen.getByTestId('pressable'));
+    expect(getEventsNames(events)).toEqual(['pressIn', 'pressOut', 'press']);
+  });
+
+  test('works on TouchableOpacity', async () => {
+    const mockOnPress = jest.fn();
+
+    render(
+      <TouchableOpacity onPress={mockOnPress}>
+        <Text>press me</Text>
+      </TouchableOpacity>,
+    );
 
-    expect(getEventsNames(events)).toEqual(['pressIn', 'press', 'pressOut']);
+    await userEvent.press(screen.getByText('press me'));
+    expect(mockOnPress).toHaveBeenCalled();
+  });
+
+  test('works on TouchableHighlight', async () => {
+    const mockOnPress = jest.fn();
+
+    render(
+      <TouchableHighlight onPress={mockOnPress}>
+        <Text>press me</Text>
+      </TouchableHighlight>,
+    );
+
+    await userEvent.press(screen.getByText('press me'));
+    expect(mockOnPress).toHaveBeenCalled();
+  });
+
+  test('works on Text', async () => {
+    const { events, logEvent } = createEventLogger();
+
+    render(
+      <Text
+        onPress={logEvent('press')}
+        onPressIn={logEvent('pressIn')}
+        onPressOut={logEvent('pressOut')}
+        onLongPress={logEvent('longPress')}
+      >
+        press me
+      </Text>,
+    );
+
+    await userEvent.press(screen.getByText('press me'));
+    expect(getEventsNames(events)).toEqual(['pressIn', 'pressOut', 'press']);
+  });
+
+  test('works on TextInput', async () => {
+    const { events, logEvent } = createEventLogger();
+
+    render(
+      <TextInput
+        placeholder="email"
+        onPressIn={logEvent('pressIn')}
+        onPressOut={logEvent('pressOut')}
+      />,
+    );
+
+    await userEvent.press(screen.getByPlaceholderText('email'));
+    expect(getEventsNames(events)).toEqual(['pressIn', 'pressOut']);
+  });
+
+  test('works on Button', async () => {
+    const { events, logEvent } = createEventLogger();
+
+    render(<Button title="press me" onPress={logEvent('press')} />);
+
+    await userEvent.press(screen.getByText('press me'));
+    expect(getEventsNames(events)).toEqual(['press']);
   });
 
   test('does not trigger event when pressable is disabled', async () => {
@@ -128,7 +197,7 @@ describe('userEvent.press with real timers', () => {
     );
     await user.press(screen.getByTestId('pressable'));
 
-    expect(getEventsNames(events)).toEqual(['pressIn', 'press', 'pressOut']);
+    expect(getEventsNames(events)).toEqual(['pressIn', 'pressOut', 'press']);
   });
 
   test('crawls up in the tree to find an element that responds to touch events', async () => {
@@ -157,50 +226,6 @@ describe('userEvent.press with real timers', () => {
     expect(mockOnLongPress).not.toHaveBeenCalled();
   });
 
-  test('works on TouchableOpacity', async () => {
-    const mockOnPress = jest.fn();
-
-    render(
-      <TouchableOpacity onPress={mockOnPress}>
-        <Text>press me</Text>
-      </TouchableOpacity>,
-    );
-    await userEvent.press(screen.getByText('press me'));
-
-    expect(mockOnPress).toHaveBeenCalled();
-  });
-
-  test('works on TouchableHighlight', async () => {
-    const mockOnPress = jest.fn();
-
-    render(
-      <TouchableHighlight onPress={mockOnPress}>
-        <Text>press me</Text>
-      </TouchableHighlight>,
-    );
-    await userEvent.press(screen.getByText('press me'));
-
-    expect(mockOnPress).toHaveBeenCalled();
-  });
-
-  test('works on Text', async () => {
-    const { events, logEvent } = createEventLogger();
-
-    render(
-      <Text
-        onPress={logEvent('press')}
-        onPressIn={logEvent('pressIn')}
-        onPressOut={logEvent('pressOut')}
-        onLongPress={logEvent('longPress')}
-      >
-        press me
-      </Text>,
-    );
-    await userEvent.press(screen.getByText('press me'));
-
-    expect(getEventsNames(events)).toEqual(['pressIn', 'press', 'pressOut']);
-  });
-
   test('does not trigger on disabled Text', async () => {
     const { events, logEvent } = createEventLogger();
 
@@ -240,22 +265,7 @@ describe('userEvent.press with real timers', () => {
     expect(events).toEqual([]);
   });
 
-  test('works on TetInput', async () => {
-    const { events, logEvent } = createEventLogger();
-
-    render(
-      <TextInput
-        placeholder="email"
-        onPressIn={logEvent('pressIn')}
-        onPressOut={logEvent('pressOut')}
-      />,
-    );
-    await userEvent.press(screen.getByPlaceholderText('email'));
-
-    expect(getEventsNames(events)).toEqual(['pressIn', 'pressOut']);
-  });
-
-  test('does not call onPressIn and onPressOut on non editable TetInput', async () => {
+  test('does not call onPressIn and onPressOut on non editable TextInput', async () => {
     const { events, logEvent } = createEventLogger();
 
     render(
@@ -270,7 +280,7 @@ describe('userEvent.press with real timers', () => {
     expect(events).toEqual([]);
   });
 
-  test('does not call onPressIn and onPressOut on TetInput with pointer events disabled', async () => {
+  test('does not call onPressIn and onPressOut on TextInput with pointer events disabled', async () => {
     const { events, logEvent } = createEventLogger();
 
     render(
@@ -295,7 +305,6 @@ describe('userEvent.press with real timers', () => {
     );
 
     await userEvent.press(screen.getByText('press me'));
-
     expect(mockOnPress).toHaveBeenCalled();
   });
 });
diff --git a/src/user-event/press/__tests__/press.test.tsx b/src/user-event/press/__tests__/press.test.tsx
index c4ff8be74..a15ac98ed 100644
--- a/src/user-event/press/__tests__/press.test.tsx
+++ b/src/user-event/press/__tests__/press.test.tsx
@@ -18,7 +18,7 @@ describe('userEvent.press with fake timers', () => {
     jest.setSystemTime(0);
   });
 
-  test('calls onPressIn, onPress and onPressOut prop of touchable', async () => {
+  test('works on Pressable', async () => {
     const { events, logEvent } = createEventLogger();
     const user = userEvent.setup();
 
@@ -31,11 +31,80 @@ describe('userEvent.press with fake timers', () => {
         testID="pressable"
       />,
     );
-    await user.press(screen.getByTestId('pressable'));
 
+    await user.press(screen.getByTestId('pressable'));
+    expect(getEventsNames(events)).toEqual(['pressIn', 'pressOut', 'press']);
     expect(events).toMatchSnapshot();
   });
 
+  test('works on TouchableOpacity', async () => {
+    const mockOnPress = jest.fn();
+
+    render(
+      <TouchableOpacity onPress={mockOnPress}>
+        <Text>press me</Text>
+      </TouchableOpacity>,
+    );
+
+    await userEvent.press(screen.getByText('press me'));
+    expect(mockOnPress).toHaveBeenCalled();
+  });
+
+  test('works on TouchableHighlight', async () => {
+    const mockOnPress = jest.fn();
+
+    render(
+      <TouchableHighlight onPress={mockOnPress}>
+        <Text>press me</Text>
+      </TouchableHighlight>,
+    );
+
+    await userEvent.press(screen.getByText('press me'));
+    expect(mockOnPress).toHaveBeenCalled();
+  });
+
+  test('works on Text', async () => {
+    const { events, logEvent } = createEventLogger();
+
+    render(
+      <Text
+        onPress={logEvent('press')}
+        onPressIn={logEvent('pressIn')}
+        onPressOut={logEvent('pressOut')}
+        onLongPress={logEvent('longPress')}
+      >
+        press me
+      </Text>,
+    );
+
+    await userEvent.press(screen.getByText('press me'));
+    expect(getEventsNames(events)).toEqual(['pressIn', 'pressOut', 'press']);
+  });
+
+  test('works on TextInput', async () => {
+    const { events, logEvent } = createEventLogger();
+
+    render(
+      <TextInput
+        placeholder="email"
+        onPressIn={logEvent('pressIn')}
+        onPressOut={logEvent('pressOut')}
+      />,
+    );
+
+    await userEvent.press(screen.getByPlaceholderText('email'));
+    expect(getEventsNames(events)).toEqual(['pressIn', 'pressOut']);
+  });
+
+  test('works on Button', async () => {
+    const { events, logEvent } = createEventLogger();
+
+    render(<Button title="press me" onPress={logEvent('press')} />);
+
+    await userEvent.press(screen.getByText('press me'));
+    expect(getEventsNames(events)).toEqual(['press']);
+  });
+
   test('does not trigger event when pressable is disabled', async () => {
     const { events, logEvent } = createEventLogger();
     const user = userEvent.setup();
@@ -129,7 +198,7 @@ describe('userEvent.press with fake timers', () => {
     );
     await user.press(screen.getByTestId('pressable'));
 
-    expect(getEventsNames(events)).toEqual(['pressIn', 'press', 'pressOut']);
+    expect(getEventsNames(events)).toEqual(['pressIn', 'pressOut', 'press']);
   });
 
   test('crawls up in the tree to find an element that responds to touch events', async () => {
@@ -158,59 +227,6 @@ describe('userEvent.press with fake timers', () => {
     expect(mockOnLongPress).not.toHaveBeenCalled();
   });
 
-  test('works on TouchableOpacity', async () => {
-    const mockOnPress = jest.fn();
-
-    render(
-      <TouchableOpacity onPress={mockOnPress}>
-        <Text>press me</Text>
-      </TouchableOpacity>,
-    );
-    await userEvent.press(screen.getByText('press me'));
-
-    expect(mockOnPress).toHaveBeenCalled();
-  });
-
-  test('works on TouchableHighlight', async () => {
-    const mockOnPress = jest.fn();
-
-    render(
-      <TouchableHighlight onPress={mockOnPress}>
-        <Text>press me</Text>
-      </TouchableHighlight>,
-    );
-    await userEvent.press(screen.getByText('press me'));
-
-    expect(mockOnPress).toHaveBeenCalled();
-  });
-
-  test('press works on Text', async () => {
-    const { events, logEvent } = createEventLogger();
-
-    render(
-      <Text
-        onPress={logEvent('press')}
-        onPressIn={logEvent('pressIn')}
-        onPressOut={logEvent('pressOut')}
-        onLongPress={logEvent('longPress')}
-      >
-        press me
-      </Text>,
-    );
-
-    await userEvent.press(screen.getByText('press me'));
-    expect(getEventsNames(events)).toEqual(['pressIn', 'press', 'pressOut']);
-  });
-
-  test('press works on Button', async () => {
-    const { events, logEvent } = createEventLogger();
-
-    render(<Button title="press me" onPress={logEvent('press')} />);
-
-    await userEvent.press(screen.getByText('press me'));
-    expect(getEventsNames(events)).toEqual(['press']);
-  });
-
   test('longPress works Text', async () => {
     const { events, logEvent } = createEventLogger();
 
@@ -268,36 +284,6 @@ describe('userEvent.press with fake timers', () => {
     expect(events).toEqual([]);
   });
 
-  test('press works on TextInput', async () => {
-    const { events, logEvent } = createEventLogger();
-
-    render(
-      <TextInput
-        placeholder="email"
-        onPressIn={logEvent('pressIn')}
-        onPressOut={logEvent('pressOut')}
-      />,
-    );
-
-    await userEvent.press(screen.getByPlaceholderText('email'));
-    expect(getEventsNames(events)).toEqual(['pressIn', 'pressOut']);
-  });
-
-  test('longPress works on TextInput', async () => {
-    const { events, logEvent } = createEventLogger();
-
-    render(
-      <TextInput
-        placeholder="email"
-        onPressIn={logEvent('pressIn')}
-        onPressOut={logEvent('pressOut')}
-      />,
-    );
-
-    await userEvent.longPress(screen.getByPlaceholderText('email'));
-    expect(getEventsNames(events)).toEqual(['pressIn', 'pressOut']);
-  });
-
   test('does not call onPressIn and onPressOut on non editable TextInput', async () => {
     const { events, logEvent } = createEventLogger();
 
@@ -372,3 +358,27 @@ describe('userEvent.press with fake timers', () => {
     expect(consoleErrorSpy).not.toHaveBeenCalled();
   });
 });
+
+function Component() {
+  const [mounted, setMounted] = React.useState(true);
+
+  const onPressIn = () => {
+    setMounted(false);
+  };
+
+  return (
+    <View>
+      {mounted && (
+        <Pressable onPressIn={onPressIn}>
+          <Text>Unmount</Text>
+        </Pressable>
+      )}
+    </View>
+  );
+}
+
+test('unmounts component', async () => {
+  render(<Component />);
+  await userEvent.press(screen.getByText('Unmount'));
+  expect(screen.queryByText('Unmount')).not.toBeOnTheScreen();
+});
diff --git a/src/user-event/press/constants.ts b/src/user-event/press/constants.ts
deleted file mode 100644
index 8d237a0db..000000000
--- a/src/user-event/press/constants.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-// These are constants defined in the React Native repo
-
-// Used to define the delay before calling onPressOut after a press
-export const DEFAULT_MIN_PRESS_DURATION = 130;
-
-// Default minimum press duration to trigger a long press
-export const DEFAULT_LONG_PRESS_DELAY_MS = 500;
diff --git a/src/user-event/press/press.ts b/src/user-event/press/press.ts
index c49ea7090..7302c704a 100644
--- a/src/user-event/press/press.ts
+++ b/src/user-event/press/press.ts
@@ -7,7 +7,11 @@ import { isHostText, isHostTextInput } from '../../helpers/host-component-names'
 import { EventBuilder } from '../event-builder';
 import { UserEventConfig, UserEventInstance } from '../setup';
 import { dispatchEvent, wait } from '../utils';
-import { DEFAULT_MIN_PRESS_DURATION } from './constants';
+
+// These are constants defined in the React Native repo
+// See: https://github.com/facebook/react-native/blob/50e38cc9f1e6713228a91ad50f426c4f65e65e1a/packages/react-native/Libraries/Pressability/Pressability.js#L264
+export const DEFAULT_MIN_PRESS_DURATION = 130;
+export const DEFAULT_LONG_PRESS_DELAY_MS = 500;
 
 export interface PressOptions {
   duration?: number;
@@ -16,7 +20,6 @@ export interface PressOptions {
 export async function press(this: UserEventInstance, element: ReactTestInstance): Promise<void> {
   await basePress(this.config, element, {
     type: 'press',
-    duration: 0,
   });
 }
 
@@ -27,13 +30,13 @@ export async function longPress(
 ): Promise<void> {
   await basePress(this.config, element, {
     type: 'longPress',
-    duration: options?.duration ?? 500,
+    duration: options?.duration ?? DEFAULT_LONG_PRESS_DELAY_MS,
   });
 }
 
 interface BasePressOptions {
   type: 'press' | 'longPress';
-  duration: number;
+  duration?: number;
 }
 
 const basePress = async (
@@ -73,16 +76,17 @@ const emitPressablePressEvents = async (
 
   dispatchEvent(element, 'responderGrant', EventBuilder.Common.responderGrant());
 
-  await wait(config, options.duration);
+  const duration = options.duration ?? DEFAULT_MIN_PRESS_DURATION;
+  await wait(config, duration);
 
   dispatchEvent(element, 'responderRelease', EventBuilder.Common.responderRelease());
 
   // React Native will wait for minimal delay of DEFAULT_MIN_PRESS_DURATION
   // before emitting the `pressOut` event. We need to wait here, so that
   // `press()` function does not return before that.
-  if (DEFAULT_MIN_PRESS_DURATION - options.duration > 0) {
+  if (DEFAULT_MIN_PRESS_DURATION - duration > 0) {
     await act(async () => {
-      await wait(config, DEFAULT_MIN_PRESS_DURATION - options.duration);
+      await wait(config, DEFAULT_MIN_PRESS_DURATION - duration);
     });
   }
 };
@@ -118,11 +122,22 @@ async function emitTextPressEvents(
   await wait(config);
   dispatchEvent(element, 'pressIn', EventBuilder.Common.touch());
 
-  // Emit either `press` or `longPress`.
-  dispatchEvent(element, options.type, EventBuilder.Common.touch());
-
   await wait(config, options.duration);
+
+  // Long press events are emitted before `pressOut`.
+  if (options.type === 'longPress') {
+    dispatchEvent(element, 'longPress', EventBuilder.Common.touch());
+  }
+
   dispatchEvent(element, 'pressOut', EventBuilder.Common.touch());
+
+  // Regular press events are emitted after `pressOut` according to the React Native docs.
+  // See: https://reactnative.dev/docs/pressable#onpress
+  // Experimentally for very short presses (< 130ms) `press` events are actually emitted before `onPressOut`, but
+  // we will ignore that as in reality most pressed would be above the 130ms threshold.
+  if (options.type === 'press') {
+    dispatchEvent(element, 'press', EventBuilder.Common.touch());
+  }
 }
 
 /**
diff --git a/src/user-event/utils/dispatch-event.ts b/src/user-event/utils/dispatch-event.ts
index 6d284f633..d1202fd54 100644
--- a/src/user-event/utils/dispatch-event.ts
+++ b/src/user-event/utils/dispatch-event.ts
@@ -1,5 +1,6 @@
 import { ReactTestInstance } from 'react-test-renderer';
 import act from '../../act';
+import { isElementMounted } from '../../helpers/component-tree';
 
 /**
  * Basic dispatch event function used by User Event module.
@@ -9,6 +10,10 @@ import act from '../../act';
  * @param event event payload(s)
  */
 export function dispatchEvent(element: ReactTestInstance, eventName: string, ...event: unknown[]) {
+  if (!isElementMounted(element)) {
+    return;
+  }
+
   const handler = getEventHandler(element, eventName);
   if (!handler) {
     return;