Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GiftedChat flickering, wrong size #2569

Closed
levepic opened this issue Dec 17, 2024 · 14 comments
Closed

GiftedChat flickering, wrong size #2569

levepic opened this issue Dec 17, 2024 · 14 comments
Labels

Comments

@levepic
Copy link

levepic commented Dec 17, 2024

Issue Description

While 2.4.0 is perfect, upgraded to 2.6.x and its flickering. Its in a react-navigation fullscreen so there is no tab navigation. The chat appears, changes side (shrinks) then jumps back again. With exactly the same code, downgrading to 2.4.0 its perfect. Probably something about onlayout

Steps to Reproduce / Code Snippets

Its a production application with a lot of code

Expected Results

No flickering like in 2.4.0

Additional Information

  • React Native version: 0.74.0
  • react-native-gifted-chat version: 2.6.4
  • Platform(s) (iOS, Android, or both?): Android
@nahooni0511
Copy link

I’m also encountering the same issue.

It appears the problem originates from the useAnimatedKeyboard module. Setting the isStatusBarTranslucentAndroid flag to true reduces the flickering, but it still occurs during the first invocation. Completely removing the useAnimatedKeyboard line eliminates the flickering.

From my observations, useAnimatedKeyboard seems to include logic (possibly using onLayout) to measure and store view dimensions. Interestingly, the flickering stops from the second invocation onward.

To investigate further, I initialized useAnimatedKeyboard during the app’s startup and then loaded GiftedChat. This resolved the flickering but introduced new issues with keyboard functionality.

The issue can be reproduced with a navigation structure combining bottomTabNavigation and StackNavigation. When navigating to GiftedChatScreen using navigation.navigate("GiftedChatScreen"), the screen transition causes a layout rearrangement, leading to flickering.

@mrkpatchaa
Copy link

On my side, I fixed the issue by hiding the react-router (react-navigation) header on the chat screen (headerShown: false), and creating a header my self. It's not the ideal, but at least it solves the issue for me for now.

@front-end-jeko
Copy link

front-end-jeko commented Dec 24, 2024

@mrkpatchaa
I was happy, before analyzing that I already had headerShown: false on the Chat screen

@mrkpatchaa
Copy link

@front-end-jeko oops...
Depending on the way you're nesting the navigators you should check the right place.
Here is what I have, I am using expo-router
app/_layout.tsx

...
<Stack.Screen
  name="chat/[id]"
  options={{
    headerShown: false,
  }}
/>
...

app/(tabs)/_layout.tsx

...
<Tabs.Screen
  name="chats"
  options={{
    // @ts-expect-error href string
    href: '/account/chats',
    title: 'Chats',
  }}
/>
...

The chat list is in the tabs, but the chat screen is in the root stack. So the tabbar is not shown.
I navigate to each chat with a simple link

<Link
  href={{
    pathname: '/chat/[id]',
    params: { id: chat.id },
  }}
  asChild
>
...

@Kjagd
Copy link

Kjagd commented Jan 28, 2025

We also had issues with the layout jumping slightly up and down again. The react-navigation bottom tabs we were using also seemed to change, such that the navigation bar became a separate view, destroying edge-to-edge mode on Android. As @nahooni0511 hinted, the reanimated keyboard seems to be causing the issue. Seems to be fixed with this patch:

diff --git a/node_modules/react-native-gifted-chat/lib/GiftedChat.js b/node_modules/react-native-gifted-chat/lib/GiftedChat.js
index 04f5efa..bcfad88 100644
--- a/node_modules/react-native-gifted-chat/lib/GiftedChat.js
+++ b/node_modules/react-native-gifted-chat/lib/GiftedChat.js
@@ -22,8 +22,9 @@ import { Send } from './Send';
 import { SystemMessage } from './SystemMessage';
 import { Time } from './Time';
 import * as utils from './utils';
-import Animated, { useAnimatedKeyboard, useAnimatedStyle, useAnimatedReaction, useSharedValue, withTiming, runOnJS, } from 'react-native-reanimated';
+import Animated, { useAnimatedStyle, useAnimatedReaction, useSharedValue, withTiming, runOnJS, } from 'react-native-reanimated';
 import { useSafeAreaInsets } from 'react-native-safe-area-context';
+import { useReanimatedKeyboardAnimation } from "react-native-keyboard-controller";
 dayjs.extend(localizedFormat);
 function GiftedChat(props) {
     const { messages = [], initialText = '', isTyping, messageIdGenerator = () => uuidv4(), user = {}, onSend, locale = 'en', renderLoading, actionSheet = null, textInputProps, renderChatFooter = null, renderInputToolbar = null, bottomOffset = 0, focusOnInputWhenOpeningKeyboard = true, keyboardShouldPersistTaps = Platform.select({
@@ -39,14 +40,14 @@ function GiftedChat(props) {
     const [composerHeight, setComposerHeight] = useState(minComposerHeight);
     const [text, setText] = useState(() => props.text || '');
     const [isTypingDisabled, setIsTypingDisabled] = useState(false);
-    const keyboard = useAnimatedKeyboard({ isStatusBarTranslucentAndroid });
+    const keyboard = useReanimatedKeyboardAnimation();
     const trackingKeyboardMovement = useSharedValue(false);
     const debounceEnableTypingTimeoutId = useRef();
     const insets = useSafeAreaInsets();
     const keyboardOffsetBottom = useSharedValue(0);
     const contentStyleAnim = useAnimatedStyle(() => ({
         transform: [
-            { translateY: -keyboard.height.value + keyboardOffsetBottom.value },
+            { translateY: keyboard.height.value - keyboardOffsetBottom.value },
         ],
     }), [keyboard, keyboardOffsetBottom]);
     const getTextFromProp = useCallback((fallback) => {
@@ -231,7 +232,7 @@ function GiftedChat(props) {
         if (!inverted && messages?.length)
             setTimeout(() => scrollToBottom(false), 200);
     }, [messages?.length, inverted, scrollToBottom]);
-    useAnimatedReaction(() => keyboard.height.value, (value, prevValue) => {
+    useAnimatedReaction(() => -keyboard.height.value, (value, prevValue) => {
         if (prevValue !== null && value !== prevValue) {
             const isKeyboardMovingUp = value > prevValue;
             if (isKeyboardMovingUp !== trackingKeyboardMovement.value) {

@Amirmadjour
Copy link

@Kjagd Thank you mate, this works like a sharm, this fixed the problem even with the stack a tab navigation and fixed a another problem I was having (the keyboard was pushing the entire screen in the GiftedChat component), I hope you make a pull request in regard for this issue

@levepic
Copy link
Author

levepic commented Feb 2, 2025

Can you make a pull request? If this works

@Amirmadjour
Copy link

Amirmadjour commented Feb 2, 2025

@levepic Yes this works, But I cannot make a pull request because I did not fully understand what @Kjagd had changed, it may have some downsides (Till now nothing)

@Kjagd
Copy link

Kjagd commented Feb 3, 2025

Great that it works - I will not make a PR since it would introduce a somewhat unrelated package dependency on react-native-keyboard-controller. The 'proper' fix would perhaps be to fix some bug in reanimated library if that's the root cause. For reference this doc showcases the differences:
https://kirillzyusko.github.io/react-native-keyboard-controller/docs/recipes/architecture#what-is-the-difference-between-useanimatedkeyboard-from-react-native-reanimated-and-this-library

@kesha-antonov
Copy link
Collaborator

We also had issues with the layout jumping slightly up and down again. The react-navigation bottom tabs we were using also seemed to change, such that the navigation bar became a separate view, destroying edge-to-edge mode on Android. As @nahooni0511 hinted, the reanimated keyboard seems to be causing the issue. Seems to be fixed with this patch:

diff --git a/node_modules/react-native-gifted-chat/lib/GiftedChat.js b/node_modules/react-native-gifted-chat/lib/GiftedChat.js
index 04f5efa..bcfad88 100644
--- a/node_modules/react-native-gifted-chat/lib/GiftedChat.js
+++ b/node_modules/react-native-gifted-chat/lib/GiftedChat.js
@@ -22,8 +22,9 @@ import { Send } from './Send';
import { SystemMessage } from './SystemMessage';
import { Time } from './Time';
import * as utils from './utils';
-import Animated, { useAnimatedKeyboard, useAnimatedStyle, useAnimatedReaction, useSharedValue, withTiming, runOnJS, } from 'react-native-reanimated';
+import Animated, { useAnimatedStyle, useAnimatedReaction, useSharedValue, withTiming, runOnJS, } from 'react-native-reanimated';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
+import { useReanimatedKeyboardAnimation } from "react-native-keyboard-controller";
dayjs.extend(localizedFormat);
function GiftedChat(props) {
const { messages = [], initialText = '', isTyping, messageIdGenerator = () => uuidv4(), user = {}, onSend, locale = 'en', renderLoading, actionSheet = null, textInputProps, renderChatFooter = null, renderInputToolbar = null, bottomOffset = 0, focusOnInputWhenOpeningKeyboard = true, keyboardShouldPersistTaps = Platform.select({
@@ -39,14 +40,14 @@ function GiftedChat(props) {
const [composerHeight, setComposerHeight] = useState(minComposerHeight);
const [text, setText] = useState(() => props.text || '');
const [isTypingDisabled, setIsTypingDisabled] = useState(false);

  • const keyboard = useAnimatedKeyboard({ isStatusBarTranslucentAndroid });
  • const keyboard = useReanimatedKeyboardAnimation();
    const trackingKeyboardMovement = useSharedValue(false);
    const debounceEnableTypingTimeoutId = useRef();
    const insets = useSafeAreaInsets();
    const keyboardOffsetBottom = useSharedValue(0);
    const contentStyleAnim = useAnimatedStyle(() => ({
    transform: [
  •        { translateY: -keyboard.height.value + keyboardOffsetBottom.value },
    
  •        { translateY: keyboard.height.value - keyboardOffsetBottom.value },
       ],
    
    }), [keyboard, keyboardOffsetBottom]);
    const getTextFromProp = useCallback((fallback) => {
    @@ -231,7 +232,7 @@ function GiftedChat(props) {
    if (!inverted && messages?.length)
    setTimeout(() => scrollToBottom(false), 200);
    }, [messages?.length, inverted, scrollToBottom]);
  • useAnimatedReaction(() => keyboard.height.value, (value, prevValue) => {
  • useAnimatedReaction(() => -keyboard.height.value, (value, prevValue) => {
    if (prevValue !== null && value !== prevValue) {
    const isKeyboardMovingUp = value > prevValue;
    if (isKeyboardMovingUp !== trackingKeyboardMovement.value) {

Interesting
Thanks for the ideas! Didn't know about this package

@kesha-antonov
Copy link
Collaborator

Seems like react-native-keyboard-controller doesn't allow to use Expo Go
Other than that it is good idea to use this lib

@alexstock1
Copy link

@kesha-antonov on gifted chat version 2.8.0 it still jumping

@kesha-antonov
Copy link
Collaborator

@kesha-antonov on gifted chat version 2.8.0 it still jumping

You can submit PR

@alexstock1
Copy link

alexstock1 commented Feb 27, 2025

We found that the problem is caused by react-native-keyboard-controller only on Android, so, we disabled. It might be related to the new architecture migration, but we're not sure. For now, we'll leave it as a to-do. At least the header is no longer jumping.

diff --git a/node_modules/react-native-gifted-chat/lib/GiftedChat/index.js b/node_modules/react-native-gifted-chat/lib/GiftedChat/index.js
index 4fc42d2..5bf2f11 100644
--- a/node_modules/react-native-gifted-chat/lib/GiftedChat/index.js
+++ b/node_modules/react-native-gifted-chat/lib/GiftedChat/index.js
@@ -22,7 +22,7 @@ import { SystemMessage } from '../SystemMessage';
 import { Time } from '../Time';
 import * as utils from '../utils';
 import Animated, { useAnimatedStyle, useAnimatedReaction, useSharedValue, withTiming, runOnJS, } from 'react-native-reanimated';
-import { KeyboardProvider, useReanimatedKeyboardAnimation } from 'react-native-keyboard-controller';
+import { KeyboardProvider, useReanimatedKeyboardAnimation, useKeyboardController } from 'react-native-keyboard-controller';
 import stylesCommon from '../styles';
 import styles from './styles';
 dayjs.extend(localizedFormat);
@@ -48,6 +48,7 @@ function GiftedChat(props) {
     const trackingKeyboardMovement = useSharedValue(false);
     const debounceEnableTypingTimeoutId = useRef(undefined);
     const keyboardOffsetBottom = useSharedValue(0);
+    const { setEnabled } = useKeyboardController();
     const contentStyleAnim = useAnimatedStyle(() => ({
         transform: [
             { translateY: keyboard.height.value - keyboardOffsetBottom.value },
@@ -180,6 +181,10 @@ function GiftedChat(props) {
         const { layout } = e.nativeEvent;
         if (layout.height <= 0)
             return;
+
+	if (Platform.OS === 'ios'){
+	   setEnabled(true);
+        }
         notifyInputTextReset();
         setIsInitialized(true);
         setComposerHeight(minComposerHeight);
@@ -279,7 +284,7 @@ function GiftedChat(props) {
     </GiftedChatContext.Provider>);
 }
 function GiftedChatWrapper(props) {
-    return (<KeyboardProvider>
+    return (<KeyboardProvider enabled={false}>
       <GiftedChat {...props}/>
     </KeyboardProvider>);
 }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

8 participants