How to Create Custom MapView Component in React Native Gifted Chat

I am a React / React Native Software Engineer
React Native Gifted Chat is a feature rich chat UI for React Native & Web. I would like to show you, how to create a custom view for gifted chat component. We will build a map view component for the react native gifted chat. When there is location property in the chat, we will display react native maps MapView instead of default chat bubble.
Link to the Working Expo Snack is attached at the bottom of the article.
I have tried to explain the same in this video as well.
If you have not yet installed go ahead and install react native gifted chat
yarn add react-native-gifted-chator npm i react-native-gifted-chat
We also need react native maps for displaying maps. Install react native maps into the application.
yarn add react-native-maps -E or npm i react-native-maps
Add a gifted chat component to the application
import React, { useState, useCallback, useEffect } from 'react';
import { TouchableOpacity, Linking, Platform } from 'react-native';
import { GiftedChat, Bubble } from 'react-native-gifted-chat';
import MapView from 'react-native-maps';
// creating custom view in react native gifted chat
const LocationView = ({ location }) => {
const openMaps = () => {
const url = Platform.select({
ios: `http://maps.apple.com/?ll=${location.latitude},${location.longitude}`,
android: `http://maps.google.com/?q=${location.latitude},${location.longitude}`,
});
Linking.canOpenURL(url)
.then((supported) => {
if (supported) {
return Linking.openURL(url);
}
})
.catch((err) => {
console.error('An error occurred', err);
});
};
return (
<TouchableOpacity
onPress={openMaps}
style={{ backgroundColor: 'gray', width: 250, height: 250 }}>
<MapView
style={{ height: 250, width: 250 }}
region={{
latitude: location.latitude,
longitude: location.longitude,
}}
annotations={[
{
latitude: location.latitude,
longitude: location.longitude,
},
]}
scrollEnabled={false}
zoomEnabled={false}
/>
</TouchableOpacity>
);
};
export function Example() {
const [messages, setMessages] = useState([]);
const renderBubble = (props) => {
const { currentMessage } = props;
if (currentMessage.location) {
return <LocationView location={currentMessage.location} />;
}
return <Bubble {...props} />;
};
useEffect(() => {
setMessages([
{
_id: 1,
text: 'Hello developer',
location: {
latitude: 37.78825,
longitude: -122.4324,
},
createdAt: new Date(),
user: {
_id: 2,
name: 'React Native',
avatar: 'https://placeimg.com/140/140/any',
},
},
]);
}, []);
const onSend = useCallback((messages = []) => {
setMessages((previousMessages) =>
GiftedChat.append(previousMessages, messages)
);
}, []);
return (
<GiftedChat
renderBubble={renderBubble}
messages={messages}
onSend={(messages) => onSend(messages)}
user={{
_id: 1,
}}
/>
);
}
export default Example;
We need to implement renderBubble function to check for location coordinates in the message object and display MapView in case of coordinates.
const renderBubble = (props) => {
const { currentMessage } = props;
if (currentMessage.location) {
return <LocationView location={currentMessage.location} />;
}
return <Bubble {...props} />;
};
Wrapping the MapView with TouchableOpacity will help to open the coordinates in the respective map application based on Platform on click.
const openMaps = () => {
const url = Platform.select({
ios: `[http://maps.apple.com/?ll=${location.latitude},${location.longitude}`](http://maps.apple.com/?ll=${location.latitude},${location.longitude}`),
android: `[http://maps.google.com/?q=${location.latitude},${location.longitude}`](http://maps.google.com/?q=${location.latitude},${location.longitude}`),
});
Linking.canOpenURL(url)
.then((supported) => {
if (supported) {
return Linking.openURL(url);
}
})
.catch((err) => {
console.error("An error occurred", err);
});
};



