We’re going to create a React Native application that will act as a Websockets client and communicate with a remote server. WebSockets is a popular, simple and robust web communication protocol enabling real-time communication between client and server.
Hardware
- Android device
- Computer for programming
- USB cable to connect Android device to PC
React Native project configuration
To communicate via Websocket, we’re going to use the Websocket library, react-use-websocket
npm install --save react-use-websocket
Utilisation de la librairie
From the library, we import the objects and functions we are interested in
import useWebSocket, { ReadyState } from 'react-use-websocket';
- ReadyState server connection status
- useWebScoket to initialize a websockets connection
We then create a functional component with the desired states
const [ipAddress, setIpAddress] = useState('');
const [ipServer, setIpServer] = useState('ws://192.168.1.52:8765');
const [messageText, setMessageText] = useState("");
const [messageHistory, setMessageHistory] = useState([]);
const { sendMessage, sendJsonMessage, lastMessage, lastJsonMessage, readyState } = useWebSocket(ipServer);
const connectionStatus = {
[ReadyState.CONNECTING]: 'Connecting',
[ReadyState.OPEN]: 'Open',
[ReadyState.CLOSING]: 'Closing',
[ReadyState.CLOSED]: 'Closed',
[ReadyState.UNINSTANTIATED]: 'Uninstantiated',
}[readyState];
const paramCmd = {
type: 'setParam',
param1: 30,
param2: 2.3,
}
In the states we retrieve the functions and states of useWebSokcet
- sendMessage the function for sending messages in String format
- sendJsonMessage for sending messages in JSON format
- lastMessage contains the server response in String format
- lastJsonMessage contains the last server message in JSON format
- readyState contains the connection state
We also define a constant in Json paramCmd format.
We use a useEffect hook to retrieve the device’s IP address and manage the messages received from the server.
useEffect(() => {
const fetchIpAddress = async () => {
const ip = await NetworkInfo.getIPV4Address();
setIpAddress(ip);
console.log("ip adresses ; ", ip)
};
fetchIpAddress();
if (lastMessage !== null) {
setMessageHistory((prev) => prev.concat(lastMessage));
}
if (lastJsonMessage !== null) {
console.log(JSON.stringify(lastJsonMessage));
}
return () => {
};
}, [lastMessage, setMessageHistory,lastJsonMessage]);
Finally, we create the application rendering with the following elements
return (
<View style={styles.mainBody}>
<Text
style={styles.mainTitle}>
AC Websocket Terminal
</Text>
<ScrollView>
<View style={styles.deviceItem}>
<View style={{flex:2}}>
<Text style={styles.deviceName}>{ipAddress}</Text>
<Text style={styles.deviceInfo}>{connectionStatus}</Text>
</View>
<TouchableOpacity
onPress={() => sendJSON()}
disabled={readyState !== ReadyState.OPEN}
style={styles.deviceButton}>
<Text
style={styles.buttonText}>
Send JSON
</Text>
</TouchableOpacity>
</View>
<View
style={styles.inputBar}>
<TextInput
style={styles.textInput}
placeholder="Enter a message"
value={messageText}
onChangeText={(text) => setMessageText(text)
}
/>
<TouchableOpacity
onPress={() => sendMessage(messageText)}
disabled={readyState !== ReadyState.OPEN}
style={[styles.sendButton]}>
<Text
style={styles.buttonText}>
SEND
</Text>
</TouchableOpacity>
</View>
<TextInput
placeholder="Server IP"
onChangeText={setIpServer}
value={ipServer}
/>
<View style={{flex:1,minHeight:200}}>
<Text>Received Message:</Text>
<ScrollView style={styles.textOutput}>
{lastMessage ? <Text>last message : {lastMessage.data}</Text> : null}
{messageHistory.map((message, idx) => (
<Text key={idx}>{message ? message.data : null}</Text>
))}
</ScrollView>
</View>
</ScrollView>
</View>
);
Creating a WebSockets server with Python
To test our application, we create a websockets server on the PC
#!/usr/bin/env python
# python3 -m pip install websockets
import json
import asyncio
from websockets.server import serve
def getIpAddress():
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.connect(("8.8.8.8", 80))
ipaddress = s.getsockname()[0]
s.close()
return ipaddress
ipaddress = getIpAddress()
port = 8765
async def echo(websocket):
async for message in websocket:
print("received from {}:{} : ".format(websocket.remote_address[0],websocket.remote_address[1]) + message)
if('{' not in message):
await websocket.send(message)
else:
request = json.loads(message)
answer = {}
if(request['type'] == 'setParam'):
answer['type'] = request['type']
if(request['param1']<100 and request['param2']>1.2):
answer['valid'] = True
for key, val in request.items():
print("\t"+key+": ", val)
else:
answer['valid'] = False
else:
answer['type'] = 'unknown'
answer['valid'] = False
await websocket.send(json.dumps(answer))
async def main():
print("Server is activated on ws://{}:{}".format(ipaddress,port))
#async with serve(echo, "localhost", 8765):
async with serve(echo, "0.0.0.0", port):
await asyncio.Future() # run forever
asyncio.run(main())
Results
Thanks to this application, we can send Strings and JSON to the server and display its responses.

Complete code for WebSockets communication with React Native
/**
* https://reactnative.dev/docs/network
* https://www.npmjs.com/package/react-use-websocket
* https://github.com/robtaussig/react-use-websocket
* test on python
* https://websockets.readthedocs.io/en/stable/
*/
import React, {useState, useEffect, useCallback} from 'react';
import {
View,
ScrollView,
Text,
TextInput,
TouchableOpacity,
StyleSheet} from 'react-native';
import { NetworkInfo } from 'react-native-network-info'
import useWebSocket, { ReadyState } from 'react-use-websocket';
const WebsocketTerminal = () => {
const [ipAddress, setIpAddress] = useState('');
const [ipServer, setIpServer] = useState('ws://192.168.1.52:8765');
const [messageText, setMessageText] = useState("");
const [messageHistory, setMessageHistory] = useState([]);
const { sendMessage, sendJsonMessage, lastMessage, lastJsonMessage, readyState } = useWebSocket(ipServer);
useEffect(() => {
const fetchIpAddress = async () => {
const ip = await NetworkInfo.getIPV4Address();
setIpAddress(ip);
console.log("ip adresses ; ", ip)
};
fetchIpAddress();
if (lastMessage !== null) {
setMessageHistory((prev) => prev.concat(lastMessage));
}
if (lastJsonMessage !== null) {
console.log(JSON.stringify(lastJsonMessage));
}
return () => {
};
}, [lastMessage, setMessageHistory,lastJsonMessage]);
const connectionStatus = {
[ReadyState.CONNECTING]: 'Connecting',
[ReadyState.OPEN]: 'Open',
[ReadyState.CLOSING]: 'Closing',
[ReadyState.CLOSED]: 'Closed',
[ReadyState.UNINSTANTIATED]: 'Uninstantiated',
}[readyState];
const sendJSON = () => {
const paramCmd = {
type: 'setParam',
param1: 30,
param2: 2.3,
}
sendJsonMessage(paramCmd);
}
return (
<View style={styles.mainBody}>
<Text
style={styles.mainTitle}>
AC Websocket Terminal
</Text>
<ScrollView>
<View style={styles.deviceItem}>
<View style={{flex:2}}>
<Text style={styles.deviceName}>{ipAddress}</Text>
<Text style={styles.deviceInfo}>{connectionStatus}</Text>
</View>
<TouchableOpacity
onPress={() => sendJSON()}
disabled={readyState !== ReadyState.OPEN}
style={styles.deviceButton}>
<Text
style={styles.buttonText}>
Send JSON
</Text>
</TouchableOpacity>
</View>
<View
style={styles.inputBar}>
<TextInput
style={styles.textInput}
placeholder="Enter a message"
value={messageText}
onChangeText={(text) => setMessageText(text)
}
/>
<TouchableOpacity
onPress={() => sendMessage(messageText)}
disabled={readyState !== ReadyState.OPEN}
style={[styles.sendButton]}>
<Text
style={styles.buttonText}>
SEND
</Text>
</TouchableOpacity>
</View>
<TextInput
placeholder="Server IP"
onChangeText={setIpServer}
value={ipServer}
/>
<View style={{flex:1,minHeight:200}}>
<Text>Received Message:</Text>
<ScrollView style={styles.textOutput}>
{lastMessage ? <Text>last message : {lastMessage.data}</Text> : null}
{messageHistory.map((message, idx) => (
<Text key={idx}>{message ? message.data : null}</Text>
))}
</ScrollView>
</View>
</ScrollView>
</View>
);
}
export default WebsocketTerminal;
let BACKGROUND_COLOR = "#161616"; //191A19
let BUTTON_COLOR = "#346751"; //1E5128
let ERROR_COLOR = "#C84B31"; //4E9F3D
let TEXT_COLOR = "#ECDBBA"; //D8E9A8
var styles = StyleSheet.create({
mainBody: { flex: 1, justifyContent: 'center', backgroundColor: BACKGROUND_COLOR},
mainTitle:{
color: TEXT_COLOR,
fontSize: 30,
textAlign: 'center',
borderBottomWidth: 2,
borderBottomColor: ERROR_COLOR,
},
backgroundVideo: {
borderWidth: 2,
borderColor: 'red',
position: 'absolute',
top: 0,
left: 0,
bottom: 0,
right: 0,
},
webVideo: {
borderWidth: 2,
borderColor: 'green',
position: 'absolute',
top: 0,
left: 0,
bottom: 0,
right: 0,
},
buttonText: {
color: TEXT_COLOR,
fontWeight: 'bold',
fontSize: 12,
textAlign: 'center',
textAlignVertical: 'center',
},
sendButton: {
backgroundColor: BUTTON_COLOR,
padding: 15,
borderRadius: 15,
margin: 2,
paddingHorizontal: 20,
},
deviceItem: {
flexDirection: 'row',
flex: 3,
marginBottom: 2,
},
deviceName: {
fontSize: 14,
fontWeight: 'bold',
},
deviceInfo: {
fontSize: 8,
},
deviceButton: {
backgroundColor: '#2196F3',
padding: 10,
borderRadius: 10,
margin: 2,
paddingHorizontal: 20,
},
inputBar:{
flexDirection: 'row',
justifyContent: 'space-between',
margin: 5,
},
textInput:{
backgroundColor: '#888888',
margin: 2,
borderRadius: 15,
flex:3,
},
textOutput:{
backgroundColor: '#333333',
margin: 10,
borderRadius: 2,
borderWidth: 1,
borderColor: '#EEEEEE',
textAlignVertical: 'top',
}
});