RN: Unbreak Rules of React in RNTesterPlatformTestEventRecorder (#51441)

Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/51441

Refactors `RNTesterPlatformTestEventRecorder` so that it does not use `useMemo` from an instance method.

Instead, this diff changes the module to export a hook by the same name, `useRecorderTestEventHandlers`.

Changelog:
[Internal]

Reviewed By: SamChou19815

Differential Revision: D74950333

fbshipit-source-id: 6cb222a6ec077abadbdc7008e822645aba3d07f6
This commit is contained in:
Tim Yung
2025-05-18 08:08:24 -07:00
committed by Facebook GitHub Bot
parent 3371fb57b7
commit 55cf1e7fd3
4 changed files with 50 additions and 39 deletions
@@ -26,7 +26,7 @@ type EventRecord = {
event: Object,
};
class RNTesterPlatformTestEventRecorder {
export default class RNTesterPlatformTestEventRecorder {
allRecords: Array<EventRecord> = [];
relevantEvents: Array<string> = [];
rawOrder: number = 1;
@@ -101,41 +101,34 @@ class RNTesterPlatformTestEventRecorder {
};
}
useRecorderTestEventHandlers(
createRecorderTestEventHandlers(
targetNames: $ReadOnlyArray<string>,
callback?: (event: Object, eventType: string, targetName: string) => void,
): $ReadOnly<{[targetName: string]: ViewProps}> {
// Yes this method exists as a class's prototype method but it will still only be used
// in functional components
// prettier-ignore
// $FlowFixMe[react-rule-hook]
return useMemo(() => { // eslint-disable-line react-hooks/rules-of-hooks
const result: {[targetName: string]: ViewProps} = {};
for (const targetName of targetNames) {
const recordedEventHandler =
this._generateRecordedEventHandlerWithCallback(
targetName,
(event, eventType) =>
callback && callback(event, eventType, targetName),
);
// $FlowFixMe[incompatible-call]
const eventListenerProps = this.relevantEvents.reduce(
(acc: ViewProps, eventName) => {
const eventPropName =
'on' + eventName[0].toUpperCase() + eventName.slice(1);
return {
...acc,
[eventPropName]: (e => {
recordedEventHandler(e, eventName);
}) as $FlowFixMe,
};
},
{},
const result: {[targetName: string]: ViewProps} = {};
for (const targetName of targetNames) {
const recordedEventHandler =
this._generateRecordedEventHandlerWithCallback(
targetName,
(event, eventType) => callback?.(event, eventType, targetName),
);
result[targetName] = eventListenerProps;
}
return result;
}, [callback, targetNames]);
// $FlowFixMe[incompatible-call]
const eventListenerProps = this.relevantEvents.reduce(
(acc: ViewProps, eventName) => {
const eventPropName =
'on' + eventName[0].toUpperCase() + eventName.slice(1);
return {
...acc,
[eventPropName]: (e => {
recordedEventHandler(e, eventName);
}) as $FlowFixMe,
};
},
{},
);
result[targetName] = eventListenerProps;
}
return result;
}
getRecords(): Array<EventRecord> {
@@ -176,4 +169,13 @@ class RNTesterPlatformTestEventRecorder {
}
}
export default RNTesterPlatformTestEventRecorder;
export function useRecorderTestEventHandlers(
eventRecorder: RNTesterPlatformTestEventRecorder,
targetNames: $ReadOnlyArray<string>,
callback?: (event: Object, eventType: string, targetName: string) => void,
): $ReadOnly<{[targetName: string]: ViewProps}> {
return useMemo(
() => eventRecorder.createRecorderTestEventHandlers(targetNames, callback),
[eventRecorder, targetNames, callback],
);
}
@@ -11,7 +11,9 @@
import type {PlatformTestComponentBaseProps} from '../PlatformTest/RNTesterPlatformTestTypes';
import RNTesterPlatformTest from '../PlatformTest/RNTesterPlatformTest';
import RNTesterPlatformTestEventRecorder from '../PlatformTest/RNTesterPlatformTestEventRecorder';
import RNTesterPlatformTestEventRecorder, {
useRecorderTestEventHandlers,
} from '../PlatformTest/RNTesterPlatformTestEventRecorder';
import * as React from 'react';
import {useCallback, useState} from 'react';
import {StyleSheet, View} from 'react-native';
@@ -126,7 +128,8 @@ function PointerEventPointerMoveAcrossTestCase(
[eventRecorder, pointermove_across],
);
const eventProps = eventRecorder.useRecorderTestEventHandlers(
const eventProps = useRecorderTestEventHandlers(
eventRecorder,
targetNames,
eventHandler,
);
@@ -11,7 +11,9 @@
import type {PlatformTestComponentBaseProps} from '../PlatformTest/RNTesterPlatformTestTypes';
import RNTesterPlatformTest from '../PlatformTest/RNTesterPlatformTest';
import RNTesterPlatformTestEventRecorder from '../PlatformTest/RNTesterPlatformTestEventRecorder';
import RNTesterPlatformTestEventRecorder, {
useRecorderTestEventHandlers,
} from '../PlatformTest/RNTesterPlatformTestEventRecorder';
import * as React from 'react';
import {useCallback, useState} from 'react';
import {StyleSheet, View} from 'react-native';
@@ -102,7 +104,8 @@ function PointerEventPointerMoveBetweenTestCase(
[eventRecorder, pointermove_between],
);
const eventProps = eventRecorder.useRecorderTestEventHandlers(
const eventProps = useRecorderTestEventHandlers(
eventRecorder,
targetNames,
eventHandler,
);
@@ -12,7 +12,9 @@ import type {PlatformTestComponentBaseProps} from '../PlatformTest/RNTesterPlatf
import type {PointerEvent} from 'react-native';
import RNTesterPlatformTest from '../PlatformTest/RNTesterPlatformTest';
import RNTesterPlatformTestEventRecorder from '../PlatformTest/RNTesterPlatformTestEventRecorder';
import RNTesterPlatformTestEventRecorder, {
useRecorderTestEventHandlers,
} from '../PlatformTest/RNTesterPlatformTestEventRecorder';
import * as React from 'react';
import {useCallback, useState} from 'react';
import {StyleSheet, View} from 'react-native';
@@ -111,7 +113,8 @@ function PointerEventPointerMoveEventOrderTestCase(
[endMoved, eventRecorder, pointer_test, startMoved],
);
const eventProps = eventRecorder.useRecorderTestEventHandlers(
const eventProps = useRecorderTestEventHandlers(
eventRecorder,
['start', 'end'],
eventHandler,
);