Repository navigation
Description
Version
v5 (5.2.14)
Reanimated Version
v4 (4.7.1, react-native-worklets 0.13.1)
Gesture Handler Version
v3 (3.5.0)
Platforms
iOS (React Native 0.87, New Architecture)
What happened?
A keyboard that opens right after another one closed is sometimes ignored. The sheet stays where it was with the keyboard hidden, so its content ends up under the keyboard.
The reaction to keyboard changes in BottomSheet.tsx keys on the sum of status and height:
useAnimatedReaction(
() =>
animatedKeyboardState.get().status + animatedKeyboardState.get().height,
(result, _previousResult) => {
if (result === _previousResult) {
return;
}
...KEYBOARD_STATUS is SHOWN = 1 and HIDDEN = 2, and on hide the state keeps the previous height. So if the keyboard closes at height h and the next one opens at h + 1:
- after hide:
HIDDEN (2) + h - after show:
SHOWN (1) + (h + 1), which is the same value
The reaction returns early, evaluatePosition(ANIMATION_SOURCE.KEYBOARD) never runs, and the sheet keeps its no-keyboard position even though animatedKeyboardState now says SHOWN with the new height.
We hit it in a dynamic-height BottomSheetModal (keyboardBehavior="interactive") with two steps:
- An email field (default keyboard, autocorrect off). On iPhone 18 Pro / iOS 27 the keyboard is 301pt.
- On submit, the email step is replaced by a one-time-code step whose input uses a number pad, which is 302pt.
Logging animatedKeyboardState and animatedPosition every 150ms after the second step mounts:
652ms kb=2 target=undefined h=301 pos=495
985ms kb=1 target=2728 h=302 pos=495 <- keyboard shown, position unchanged
1135ms kb=1 target=2728 h=302 pos=495
With a 379pt sheet on an 874pt screen, the expected position is 874 − 302 − 379 = 193. It stays at 495, the no-keyboard position. Whether it happens depends on the two keyboard heights differing by exactly 1pt, so it looks intermittent across devices and keyboard configurations (suggestion bar on or off).
Reproduction steps
- Present a
BottomSheetModalwithenableDynamicSizingandkeyboardBehavior="interactive". - Inside it, focus a
BottomSheetTextInputwhose keyboard is heighth(for example an email field withautoCorrect={false}). - Blur it (
Keyboard.dismiss()), then focus a secondBottomSheetTextInputwhose keyboard ish + 1(for exampleinputMode="numeric"/ number pad). - The sheet does not move up; the second input is under the keyboard.
To confirm the cause without matching keyboard heights, set animatedKeyboardState from { status: HIDDEN, height: 301 } to { status: SHOWN, height: 302 }: the keyboard reaction does not fire.
Reproduction sample
const Repro = () => {
const ref = useRef<BottomSheetModal>(null);
const [step, setStep] = useState<'email' | 'code'>('email');
useEffect(() => ref.current?.present(), []);
return (
<BottomSheetModal ref={ref} keyboardBehavior="interactive" keyboardBlurBehavior="restore">
<BottomSheetView style={{ padding: 16, gap: 16 }}>
{step === 'email' ? (
<>
<BottomSheetTextInput autoFocus keyboardType="email-address" autoCorrect={false} />
<Button title="Next" onPress={() => { Keyboard.dismiss(); setStep('code'); }} />
</>
) : (
<>
<Text>Enter the code</Text>
<BottomSheetTextInput autoFocus inputMode="numeric" />
<Button title="Verify" onPress={() => {}} />
</>
)}
</BottomSheetView>
</BottomSheetModal>
);
};Whether it reproduces depends on the device's keyboard heights, as described above.
Suggested fix
Key the reaction on a value that can't collide, e.g. a string:
--- a/src/components/bottomSheet/BottomSheet.tsx
+++ b/src/components/bottomSheet/BottomSheet.tsx
@@ useAnimatedReaction(
- () =>
- animatedKeyboardState.get().status + animatedKeyboardState.get().height,
+ () =>
+ `${animatedKeyboardState.get().status}:${animatedKeyboardState.get().height}`,
(result, _previousResult) => {(Same change in lib/module and lib/commonjs.) We apply this with yarn patch and the sheet now lifts above the keyboard every time in the scenario above (previously it failed about every other attempt).
Relevant log output
See the animatedKeyboardState / animatedPosition log above.
Activity
github-actions commentedon Nov 12, 2026
Hello @BuiHung1612 👋, this issue is being automatically closed and locked because it does not follow the issue template.