The useAnimatedKeyboard shared value is not receiving the live keyboard height on iOS 26
Description
On iOS 18.6, the useAnimatedKeyboard shared value progressively updates until it reaches the final keyboard height. As a result, the animated view (mimicking a KeyboardAvoidingView) smoothly slides along with the keyboard.
https://github.com/user-attachments/assets/01113512-2b8d-4fd5-9b6a-a9db658c6d4e
However, on iOS 26.0, useAnimatedKeyboard only updates to the final keyboard height, causing the animated view (KeyboardAvoidingView mimic) to snap directly to the final height after the keyboard has fully opened.
https://github.com/user-attachments/assets/d27f2979-68a2-43eb-ba31-b5d699b98f0d
Steps to reproduce
-
Clone this repo: https://github.com/vadivazhagan-capmint/reanimated-useAnimatedKeyboard-reproduce.git or copy the code snippet below and wrap it around the view that requires KeyboardAvoidingView.
-
Run the project on iOS 26.0 and iOS 18.6.
Snippet
import React, { PropsWithChildren } from 'react';
import { ViewStyle } from 'react-native';
import Animated, { useAnimatedKeyboard, useAnimatedStyle } from 'react-native-reanimated';
interface IOwnProps extends PropsWithChildren {
customStyle?: ViewStyle;
}
const AnimatedKeyboardAvoidingView: React.FC<IOwnProps> = ({
children,
customStyle,
}) => {
const keyboard = useAnimatedKeyboard();
const footerAnimatedStyle = useAnimatedStyle(() => {
console.log('[Marker] Animated Keyboard Height', keyboard.height.value)
return {
transform: [
{
translateY: -keyboard.height.value
}
]
}
});
return (
<Animated.View style={[customStyle, footerAnimatedStyle]}>
{children}
</Animated.View>
);
};
export default AnimatedKeyboardAvoidingView;
In this example repository, I am using React Native 0.81.4, but the issue occurs regardless of the React Native version on iOS 26.0.
Snack or a link to a repository
https://github.com/vadivazhagan-capmint/reanimated-useAnimatedKeyboard-reproduce
Reanimated version
4.1.0
Worklets version
0.5.1
React Native version
0.78.2
Platforms
iOS
JavaScript runtime
Hermes
Workflow
React Native CLI
Architecture
New Architecture (Fabric renderer)
Build type
No response
Device
Real device, iOS simulator
Host machine
macOS
Device model
No response
Acknowledgements
Yes
I confirm, I encountered the same problem
@tjzel can you confirm? I see this in multiple projects
Can confirm
Same issue
I have the same issue. I thought I was not using the hook correctly. I'm using reanimated 3.x.x and iOS 26.1 So this looks like iOS 26 specific issue.
Any update on the fix for this issue?
Here as well. Work around is just to wrap it in WithTiming but it only fires after the keyboard animation settles
useAnimatedReaction(
() => keyboard.state.value,
(currKeyboard, prevKeyboar) => {
if (!(currKeyboard === 2 && prevKeyboar === 2)) {
debouncedKeyboardHeight.value =
Platform.OS === "ios"
? withTiming(Math.min(keyboard.height.value, 300), { duration: 500 })
: Math.min(keyboard.height.value, 300);
}
},
);
Hey guys!
iOS 26 introduced several breaking changes in keyboard behavior, and there is currently no quick universal fix available. As an alternative, you can use the react-native-keyboard-controller library, which isn't flawless, but can serve as a replacement to handle the new keyboard behavior on iOS 26.
Here are some steps showing what you should do to migrate:
- Follow this Getting Started guide to install the library
- Implement the following helper hook which will work in a similar way to the Reanimated's
useAnimatedKeyboardhook
import { useKeyboardHandler } from 'react-native-keyboard-controller';
import { KeyboardState, useSharedValue } from 'react-native-reanimated';
export function useAnimatedKeyboard() {
const height = useSharedValue(0);
const state = useSharedValue(KeyboardState.UNKNOWN);
useKeyboardHandler(
{
onStart: (e) => {
'worklet';
state.set(e.height > 0 ? KeyboardState.OPENING : KeyboardState.CLOSING);
},
onMove: (e) => {
'worklet';
height.set(e.height);
},
onEnd: (e) => {
'worklet';
state.set(e.height > 0 ? KeyboardState.OPEN : KeyboardState.CLOSED);
height.set(e.height);
},
onInteractive: (e) => {
'worklet';
height.set(e.height);
},
},
[]
);
return { height, state };
}
- Use the
useAnimatedKeyboardimplementation from the point 2. as the replacement for theuseAnimatedKeyboardfrom Reanimated
Please let me know if have any more questions!