Framework Integration
Using Core with React Native
Getting started
Chat Widget
- Getting Started
- Core Integration
- Core Package Deep Dive
- Framework Integration
- Customization
- Reference
AI Phone Support
AI WhatsApp Support
AI SMS Support
AI Email Support
Training your AI
Native Integrations
AI Safety
Framework Integration
Using Core with React Native
Learn how to integrate the OpenCX Widget Core Package with React Native applications
The core package can be used with React Native to create native chat experiences. This guide shows you how to implement chat functionality in your React Native app.
Setup with React Native
import {
createChat,
createConfig,
ApiCaller,
Platform,
type MessageType
} from '@opencx/widget';
import AsyncStorage from '@react-native-async-storage/async-storage';
import { createContext, useContext, useState, useEffect } from 'react';
// Create chat context
const ChatContext = createContext<{
messages: MessageType[];
sendMessage: (content: string) => Promise<void>;
loading: boolean;
error: Error | null;
} | null>(null);
// Chat provider for React Native
export function ChatProvider({ children }: { children: React.ReactNode }) {
const [messages, setMessages] = useState<MessageType[]>([]);
const [loading, setLoading] = useState(false);
const [error, setError] = useState<Error | null>(null);
useEffect(() => {
// Initialize chat with React Native specific platform
const config = createConfig({
token: 'YOUR_BOT_TOKEN',
apiUrl: 'YOUR_API_URL',
user: {
email: "user@example.com",
name: "User Name"
}
});
const api = new ApiCaller({ config: config.getConfig() });
// Platform configuration for React Native
const platform: Platform = {
env: {
platform: 'mobile',
os: Platform.OS, // 'ios' or 'android'
},
// Use AsyncStorage for React Native
storage: {
getItem: async (key) => await AsyncStorage.getItem(key),
setItem: async (key, value) => await AsyncStorage.setItem(key, value),
removeItem: async (key) => await AsyncStorage.removeItem(key)
},
logger: {
level: 'debug',
prefix: '[OpenChat]',
enabled: __DEV__ // Only enable logging in development
}
};
const chat = createChat({ api, config, platform });
const unsubscribe = chat.chatState.subscribe((state) => {
setLoading(state.loading.isLoading);
if (state.error.hasError) {
setError(new Error(state.error.message));
return;
}
setMessages(state.messages);
});
return () => {
unsubscribe();
};
}, []);
return (
<ChatContext.Provider value={{
messages,
sendMessage: async (content) => {
// Implementation of send message
},
loading,
error
}}>
{children}
</ChatContext.Provider>
);
}
Component Examples
Chat Screen
import { View, StyleSheet, SafeAreaView } from 'react-native';
function ChatScreen() {
const { messages, loading, error } = useChat();
if (error) {
return <ErrorView error={error} />;
}
return (
<SafeAreaView style={styles.container}>
{loading && <LoadingSpinner />}
<MessageList messages={messages} />
<InputBar />
</SafeAreaView>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff'
}
});
Message List
import { FlatList, ViewToken } from 'react-native';
function MessageList({ messages }: { messages: MessageType[] }) {
const [viewableItems, setViewableItems] = useState<ViewToken[]>([]);
const onViewableItemsChanged = useCallback(({ viewableItems }) => {
setViewableItems(viewableItems);
}, []);
return (
<FlatList
data={messages}
renderItem={({ item }) => (
<MessageBubble message={item} />
)}
keyExtractor={(item, index) => `${index}-${item.id}`}
onViewableItemsChanged={onViewableItemsChanged}
viewabilityConfig={{
itemVisiblePercentThreshold: 50
}}
inverted // Show latest messages at the bottom
contentContainerStyle={styles.messageList}
/>
);
}
Message Bubble
import { View, Text, Animated } from 'react-native';
function MessageBubble({ message }: { message: MessageType }) {
const slideAnim = useRef(new Animated.Value(50)).current;
const fadeAnim = useRef(new Animated.Value(0)).current;
useEffect(() => {
Animated.parallel([
Animated.spring(slideAnim, {
toValue: 0,
useNativeDriver: true
}),
Animated.timing(fadeAnim, {
toValue: 1,
duration: 200,
useNativeDriver: true
})
]).start();
}, []);
const isUser = message.type === 'FROM_USER';
return (
<Animated.View
style={[
styles.bubble,
isUser ? styles.userBubble : styles.botBubble,
{
transform: [{ translateX: slideAnim }],
opacity: fadeAnim
}
]}
>
<Text style={styles.messageText}>
{message.type === 'FROM_BOT'
? (message as BotMessageType<{ text: string }>).data.text
: message.content
}
</Text>
</Animated.View>
);
}
Input Bar
import { TextInput, TouchableOpacity, Keyboard } from 'react-native';
function InputBar() {
const { sendMessage } = useChat();
const [input, setInput] = useState('');
const [sending, setSending] = useState(false);
const handleSend = async () => {
if (!input.trim()) return;
Keyboard.dismiss();
setSending(true);
try {
await sendMessage(input);
setInput('');
} catch (error) {
console.error('Failed to send message:', error);
} finally {
setSending(false);
}
};
return (
<View style={styles.inputContainer}>
<TextInput
style={styles.input}
value={input}
onChangeText={setInput}
placeholder="Type a message..."
editable={!sending}
multiline
/>
<TouchableOpacity
onPress={handleSend}
disabled={sending || !input.trim()}
style={[styles.sendButton, sending && styles.sendButtonDisabled]}
>
<Text style={styles.sendButtonText}>
{sending ? 'Sending...' : 'Send'}
</Text>
</TouchableOpacity>
</View>
);
}
Platform-Specific Features
Notifications
import PushNotificationIOS from '@react-native-community/push-notification-ios';
import messaging from '@react-native-firebase/messaging';
function useChatNotifications() {
useEffect(() => {
// Request permissions
async function requestUserPermission() {
const authStatus = await messaging().requestPermission();
const enabled =
authStatus === messaging.AuthorizationStatus.AUTHORIZED ||
authStatus === messaging.AuthorizationStatus.PROVISIONAL;
if (enabled) {
const token = await messaging().getToken();
// Send token to your server
}
}
// Handle incoming messages
const unsubscribe = messaging().onMessage(async remoteMessage => {
// Handle foreground messages
if (Platform.OS === 'ios') {
PushNotificationIOS.addNotificationRequest({
id: remoteMessage.messageId,
body: remoteMessage.notification.body,
title: remoteMessage.notification.title
});
}
});
requestUserPermission();
return unsubscribe;
}, []);
}
Storage
import EncryptedStorage from 'react-native-encrypted-storage';
// Secure storage implementation
const secureStorage = {
getItem: async (key: string) => {
try {
return await EncryptedStorage.getItem(key);
} catch (error) {
console.error('Error reading secure storage:', error);
return null;
}
},
setItem: async (key: string, value: string) => {
try {
await EncryptedStorage.setItem(key, value);
} catch (error) {
console.error('Error writing to secure storage:', error);
}
},
removeItem: async (key: string) => {
try {
await EncryptedStorage.removeItem(key);
} catch (error) {
console.error('Error removing from secure storage:', error);
}
}
};
Best Practices
-
Performance
- Use
FlatList
for message lists - Implement proper list item recycling
- Optimize images and media
- Use
-
Native Features
- Handle keyboard properly
- Support haptic feedback
- Implement push notifications
-
Platform Specifics
- Follow platform design guidelines
- Handle different screen sizes
- Support both iOS and Android
-
Offline Support
- Implement message queuing
- Handle reconnection gracefully
- Cache important data
-
Security
- Use encrypted storage
- Handle deep links safely
- Implement proper authentication
Was this page helpful?