react-native-gifted-chat
react-native-gifted-chat copied to clipboard
Layout shifts on android when loading chat
I'm having this issue with gifted chat. when a chat is opened, everything moves downward including header before correcting their positions and even though chats are statically defined, it takes times to load UI and chats. What am i doing wrong? This header issue happens only on android. If i comment out giftedchat component in screen, UI doesn't move downwards
Versions: RN-gifted-chats: "^2.8.0" expo: "^52.0.38"
import { View, SafeAreaView, TouchableOpacity, Text } from 'react-native';
import { useLocalSearchParams } from 'expo-router';
import { useState, useCallback, useEffect } from 'react';
import {
GiftedChat,
IMessage,
InputToolbar,
Send,
Actions,
Composer,
Time,
Bubble,
} from 'react-native-gifted-chat';
import { useUserStore } from '~/store/userStore';
import { Ionicons } from '@expo/vector-icons';
import * as DocumentPicker from 'expo-document-picker';
export default function ChatScreen() {
const { id, chatUser } = useLocalSearchParams();
const { user } = useUserStore();
const [messages, setMessages] = useState<IMessage[]>([]);
const [text, setText] = useState('');
const [isRecording, setIsRecording] = useState(false);
const [selectedFile, setSelectedFile] = useState<DocumentPicker.DocumentResult | null>(null);
const otherUser = chatUser ? JSON.parse(chatUser as string) : null;
useEffect(() => {
setMessages([
{
_id: 1,
text: "Good morning! That's great to hear. Could you share the details with me?",
createdAt: new Date(),
user: {
_id: 2,
name: 'Daniella Russel',
avatar: otherUser?.avatar,
},
},
{
_id: 2,
text: 'Please review this',
createdAt: new Date(),
user: {
_id: 2,
name: 'Daniella Russel',
avatar: otherUser?.avatar,
},
file: {
name: 'Portfolio.zip',
size: '54 KB',
type: 'application/zip',
},
},
{
_id: 3,
text: 'Sure! For starters, I recommend reallocating funds from low-yield bonds to high-growth mutual funds.',
createdAt: new Date(),
user: {
_id: 2,
name: 'Daniella Russel',
avatar: otherUser?.avatar,
},
},
]);
}, []);
const onSend = useCallback((newMessages: IMessage[] = []) => {
setMessages((previousMessages) => GiftedChat.append(previousMessages, newMessages));
}, []);
const handleAttachment = async () => {
try {
const result = await DocumentPicker.getDocumentAsync();
if (result.assets && result.assets.length > 0) {
const file = result.assets[0];
setSelectedFile(result);
// Send file message
const fileMessage: IMessage = {
_id: Math.random().toString(),
text: file.name,
createdAt: new Date(),
user: {
_id: user?._id || '',
name: user?.username,
avatar: user?.avatar,
},
file: {
name: file.name,
size: `${Math.round(file.size / 1024)} KB`,
type: file.mimeType,
},
};
onSend([fileMessage]);
}
} catch (error) {
console.error('Error picking document:', error);
}
};
const renderInputToolbar = (props: any) => (
<InputToolbar
{...props}
containerStyle={{
backgroundColor: '#f8f9fa',
borderTopWidth: 0,
paddingVertical: 8,
paddingHorizontal: 10,
}}
primaryStyle={{ alignItems: 'center' }}
/>
);
const renderActions = (props: any) => (
<Actions
{...props}
containerStyle={{
width: 40,
height: 40,
alignItems: 'center',
justifyContent: 'center',
marginLeft: 4,
marginRight: 4,
}}
icon={() => <Ionicons name="attach" size={24} color="#666" />}
onPressActionButton={handleAttachment}
/>
);
const renderSend = (props: any) => (
<Send
{...props}
disabled={!props.text && !isRecording}
containerStyle={{
width: 40,
height: 40,
alignItems: 'center',
justifyContent: 'center',
marginHorizontal: 4,
}}>
<TouchableOpacity
onPress={() => {
if (!props.text) {
setIsRecording(!isRecording);
} else {
props.onSend({ text: props.text.trim() }, true);
}
}}
className="h-8 w-8 items-center justify-center rounded-full bg-primary">
<Ionicons
name={props.text ? 'send' : isRecording ? 'stop' : 'mic'}
size={20}
color="white"
/>
</TouchableOpacity>
</Send>
);
const renderComposer = (props: any) => (
<Composer
{...props}
textInputStyle={{
backgroundColor: 'white',
borderRadius: 20,
borderWidth: 1,
borderColor: '#e2e8f0',
paddingHorizontal: 12,
paddingVertical: 8,
maxHeight: 100,
fontSize: 16,
}}
placeholderTextColor="#94a3b8"
/>
);
const renderBubble = (props: any) => (
<Bubble
{...props}
wrapperStyle={{
left: {
backgroundColor: 'white',
borderRadius: 12,
padding: 4,
marginBottom: 4,
},
right: {
backgroundColor: '#007AFF',
borderRadius: 12,
padding: 4,
marginBottom: 4,
},
}}
textStyle={{
left: {
color: '#1a1a1a',
},
right: {
color: 'white',
},
}}
/>
);
const renderTime = (props: any) => (
<Time
{...props}
timeTextStyle={{
left: {
color: '#94a3b8',
fontSize: 12,
},
right: {
color: '#94a3b8',
fontSize: 12,
},
}}
/>
);
const renderMessageFile = (props: any) => {
const { currentMessage } = props;
if (currentMessage.file) {
return (
<View className="mt-2 rounded-lg bg-gray-100 p-3">
<View className="flex-row items-center">
<Ionicons name="document-outline" size={24} color="#666" />
<View className="ml-3">
<Text className="font-medium text-sm text-gray-900">{currentMessage.file.name}</Text>
<Text className="text-xs text-gray-500">{currentMessage.file.size}</Text>
</View>
</View>
</View>
);
}
return null;
};
return (
<SafeAreaView className="flex-1 bg-gray-50">
<View className="flex-1">
<GiftedChat
messages={messages}
onSend={onSend}
user={{
_id: user?._id || '',
name: user?.username,
avatar: user?.avatar,
}}
text={text}
onInputTextChanged={setText}
renderInputToolbar={renderInputToolbar}
renderActions={renderActions}
renderSend={renderSend}
renderComposer={renderComposer}
renderBubble={renderBubble}
renderTime={renderTime}
renderMessageFile={renderMessageFile}
placeholder="Write a message..."
showAvatarForEveryMessage={false}
alwaysShowSend
minInputToolbarHeight={60}
timeFormat="HH:mm"
dateFormat="ll"
scrollToBottom
infiniteScroll
/>
</View>
</SafeAreaView>
);
}
Hi @muazazhar, I have the same problem, did you found a solution?
No
Facing the same problem only on android device. No solution found yet
I added a comment about our setup here: https://github.com/FaridSafi/react-native-gifted-chat/issues/2613#issuecomment-2786460043 might be helpful
same issue here. @Kjagd 's approach didn't help
@Kjagd Getting the same issue. Has anyone found a solution for this?
And you are positively using the edge-to-edge library? And updated your code to use it for the Status bar? It just looks related to that, but it would make sense to have a small example app in the repo here where is verified works.
Getting the same issue. Has anyone found a solution for this?
Getting the same issue. Has anyone found a solution for this?
Updated the library to the latest version fixed my issue
Updated to latest (2.8.1). Didn't worked for me
On Thu, May 8, 2025, 3:07 AM younseoryu @.***> wrote:
younseoryu left a comment (FaridSafi/react-native-gifted-chat#2602) https://github.com/FaridSafi/react-native-gifted-chat/issues/2602#issuecomment-2860512129
Getting the same issue. Has anyone found a solution for this?
Updated the library to the latest version fixed my issue
— Reply to this email directly, view it on GitHub https://github.com/FaridSafi/react-native-gifted-chat/issues/2602#issuecomment-2860512129, or unsubscribe https://github.com/notifications/unsubscribe-auth/ALWRHVO25N7B2ZAEMPY4FKT25J7YXAVCNFSM6AAAAABZHO4SJOVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDQNRQGUYTEMJSHE . You are receiving this because you were mentioned.Message ID: @.***>
I was using expo-navigation-bar to fix some edge-to-edge issues in my RN app and was seeing layout shifts on new devices when loading chat messages as well. I was able to pin it to an exact line in my code:
NavigationBar.setPositionAsync("relative");
My _layout.tsx:
const AppRootLayout = () => {
return <Stack screenOptions={{
contentStyle: { backgroundColor: "red" }
}}>
<Stack.Screen name="index" />
</Stack>
}
export default AppRootLayout;
index.tsx (working):
export default function IndexPage() {
return <View style={{ flex: 1, backgroundColor: 'red' }}>
<GiftedChat messages={[]} />
</View>
}
index.tsx (not working):
export default function IndexPage() {
useEffect(() => {
NavigationBar.setPositionAsync('relative');
}, []);
return <View style={{ flex: 1, backgroundColor: 'red' }}>
<GiftedChat messages={[]} />
</View>
}
I'm able to temporarily work around my issues by using https://docs.expo.dev/versions/latest/sdk/navigation-bar/#navigationbarsetpositionasyncposition this "hack":
import * as NavigationBar from 'expo-navigation-bar';
useEfect(() => {
NavigationBar.setPositionAsync("absolute");
}, []);
Maybe that points someone in the right direction.
Same issue
For now you can use version 2.4.0 as it helps me to remove this issue
I implemented the following solution, and it works well for me:
File path: node_modules/react-native-gifted-chat/lib/GiftedChat/index.js
function GiftedChatWrapper(props) { return ( <> {Platform.OS === 'ios' ? ( <KeyboardProvider> <GiftedChat {...props} /> </KeyboardProvider> ) : ( <GiftedChat {...props} /> )} </> ); }
I implemented the following solution, and it works well for me:
File path: node_modules/react-native-gifted-chat/lib/GiftedChat/index.js
function GiftedChatWrapper(props) { return ( <> {Platform.OS === 'ios' ? ( <KeyboardProvider> <GiftedChat {...props} /> </KeyboardProvider> ) : ( <GiftedChat {...props} /> )} </> ); }
Thanks for sharing this! Your solution fixed the issue with "react-native-gifted-chat" v2.8.1 on React Native 0.80.1. Much appreciated!
I implemented the following solution, and it works well for me:
File path: node_modules/react-native-gifted-chat/lib/GiftedChat/index.js
function GiftedChatWrapper(props) { return ( <> {Platform.OS === 'ios' ? ( <KeyboardProvider> <GiftedChat {...props} /> </KeyboardProvider> ) : ( <GiftedChat {...props} /> )} </> ); }
this onef
I implemented the following solution, and it works well for me:
File path: node_modules/react-native-gifted-chat/lib/GiftedChat/index.js
function GiftedChatWrapper(props) { return ( <> {Platform.OS === 'ios' ? ( <KeyboardProvider> <GiftedChat {...props} /> </KeyboardProvider> ) : ( <GiftedChat {...props} /> )} </> ); }
This one fixed my issue .. my issue was when i land on the chatting screen my status bar color changed ..etc
I have applied this patch Add disableKeyboardController prop to fix react-native-navigation compatibility #2650, 🚀🚀 which works fine in react-native 0.79.2 and react-native-gifted-chats: "2.8.1"
When can we expect the release update?
Thanks
Try code from master or version 3.0.0-alpha.1 Should be fixed there