Skip to content

Commit 1a93daa

Browse files
committed
Derive Pressable pressed state from testOnly_pressed (#4414)
`testOnly_pressed` forces a Pressable's pressed state (for snapshots/tests), but both v3 engines only seeded it into the initial `useState(testOnly_pressed ?? false)`. After mount, changing the prop no longer updated the functional `style`/`children`, so they showed a stale pressed state. Both engines now derive the displayed state from `testOnly_pressed ?? <pressed>` at the style/children call sites — a prop change is reflected, while interactive presses still work when the prop is unset. This matches RN's Pressable, which runs the style/children functions with the forced pressed state on every render. Follow-up to #4411. CodeRabbit flagged the stateful engine; the Touchable-based engine had the identical issue. Existing v3 suite passes (`yarn test` in `packages/react-native-gesture-handler`). The change only affects the value passed to functional `style`/`children` when `testOnly_pressed` is set.
1 parent d4fe079 commit 1a93daa

1 file changed

Lines changed: 8 additions & 3 deletions

File tree

  • packages/react-native-gesture-handler/src/components/Pressable

‎packages/react-native-gesture-handler/src/components/Pressable/Pressable.tsx‎

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ const Pressable = (props: PressableProps) => {
7979
blocksExternalGesture,
8080
};
8181

82-
const [pressedState, setPressedState] = useState(testOnly_pressed ?? false);
82+
const [pressedState, setPressedState] = useState(false);
8383

8484
const longPressTimeoutRef = useRef<number | null>(null);
8585
const pressDelayTimeoutRef = useRef<number | null>(null);
@@ -372,12 +372,17 @@ const Pressable = (props: PressableProps) => {
372372
const pointerStyle: StyleProp<ViewStyle> =
373373
Platform.OS === 'web' ? { cursor: 'pointer' } : {};
374374

375+
// `testOnly_pressed` forces the pressed state for snapshots/tests. Derive the
376+
// displayed value from it each render, keeping the interactive `pressedState`
377+
// independent (seeded to false) so clearing the prop doesn't leave it stuck.
378+
const displayPressed = testOnly_pressed ?? pressedState;
379+
375380
const styleProp =
376-
typeof style === 'function' ? style({ pressed: pressedState }) : style;
381+
typeof style === 'function' ? style({ pressed: displayPressed }) : style;
377382

378383
const childrenProp =
379384
typeof children === 'function'
380-
? children({ pressed: pressedState })
385+
? children({ pressed: displayPressed })
381386
: children;
382387

383388
const rippleColor = useMemo(() => {

0 commit comments

Comments
 (0)