The web was originally implemented on the principle of request and response: a client sends a request and a server replies with an appropriate response. When there is no requirement for data manipulation according to a client request, it’s customary to serve a static page.
When dynamic pages came along, we were introduced to the concept of GET, POST, PUT, and DELETE requests. Now a client is able to ask for custom data from a server by sending its requirements as parameters. The server then processes the request and returns a dynamic response.
Still, the fundamentals are based on request and response: the client requests, the server responds, and the connection is closed.
There is another protocol that doesn’t work like a request-response scheme known as WebSockets. In this tutorial, we’ll introduce you to the WebSockets technology and some of its common use cases. We will walk you through how to implement WebSockets in React Native by designing a message broadcast app.
The Replay is a weekly newsletter for dev and engineering leaders.
Delivered once a week, it's your curated guide to the most important conversations around frontend dev, emerging AI tools, and the state of modern software.
WebSockets is a protocol that provides full-duplex communication, which means the client and server stay connected over a single TCP connection. Unlike request-response communication, the connection doesn’t close here.
Since it’s full-duplex, the server can also send data to the client without a request. This helps in saving bandwidth and response time.
The WebSockets protocol starts with ws://. For dealing with hypertext, we use http:// or https://.
There is a range of applications for WebSockets, but we primarily use them in cases where data needs to be either broadcasted or pushed by server.
For example, a chat app server needs to send a message to a recipient as soon as the sender sends it. The server can’t wait for the client to request new messages, so it pushes them to the client using full-duplex communication. Similarly, news, trade matrix, and even social media posts are pushed in this way.
This outcome could be achieved before WebSockets entered the picture, but they were unreliable and inefficient.
For instance, many companies used long polling in which a browser sends a request but the server does not respond. The connection stays active until there is a connection timeout. In the meantime, if server has any message for the client, it responds and the connection closes. As soon as the connection closes, either due to timeout or server response, the client again sends the request. This process keeps going.
Another approach is to send an AJAX request in an interval of few seconds — say, three seconds — and get a server response, which is either a valid message or empty object. So, a new message can get delayed for, at most, three seconds. The downside of this approach is that a lot of API calls go to waste because the server doesn’t have any message to respond to.
There are four main functions that are executed during the lifecycle of WebSockets. They are called when the app establishes a connection, receives a messages, catches an error, and disconnects.
Let’s zoom in on these functions.
The first step is to establish a connection with the server. WebSockets work on their own protocol, ws://.
In React Native, we can create a connection using the following code:
var ws = new WebSocket('ws://host.com/path');
Here the link corresponds to the socket service running on the backend.
If the server accepts the connection, it notifies the client by invoking the onopen function over the WebSocket object:
ws.onopen = () => {
  // connection opened
  ws.send('something');  // send a message
};
This acts like the constructor. You can allocate resources in this function. Also, if you need to send some one-time information, such as a user identification number, to the server, you can do so here.
In a request-response policy, the client looks for a response in the sent request. This means the client knows when it will get data from the server so it stays ready to handle it. But in full-duplex communication like WebSockets, the server can send data at any time without the consent of the client.
To handle this situation, a function must be invoked when the server sends a message.
In React Native, we have an onmessage function for this:
ws.onmessage = (e) => {
  // a message was received
  console.log(e.data);
};
When there is an error, either due to poor internet connectivity or internal server errors, the onerror function is called:
ws.onerror = (e) => {
  // an error occurred
  console.log(e.message);
};
When the connection closes, either by the server or by the client, the onclose function is called. This acts like a destructor in that you can release the allocated resources.
ws.onclose = (e) => {
  // connection closed
  console.log(e.code, e.reason);
};
Now we’ve seen the complete lifecycle of WebSockets in React Native, from establishing a connection to closing it. We can write all these functions in single block as follows:
var ws = new WebSocket('ws://host.com/path');
ws.onopen = () => {
  // connection opened
  ws.send('something'); // send a message
};
ws.onmessage = (e) => {
  // a message was received
  console.log(e.data);
};
ws.onerror = (e) => {
  // an error occurred
  console.log(e.message);
};
ws.onclose = (e) => {
  // connection closed
  console.log(e.code, e.reason);
};
To show WebSockets in action, let’s create a simple message broadcasting app in Rect Native. In our demo app, a message sent from one application will be broadcast to all connected applications.
We’ll develop the server script in Node.js. Here’s the WebSockets server code:
const express = require("express");
const app = express();
const http = require("http");
const WebSocket = require("ws");
const server = http.createServer(app);
const wss = new WebSocket.Server({ server });
wss.on("connection", function connection(ws) {
  ws.on("message", function incoming(message, isBinary) {
    console.log(message.toString(), isBinary);
    wss.clients.forEach(function each(client) {
      if (client.readyState === WebSocket.OPEN) {
        client.send(message.toString());
      }
    });
  });
});
app.get("/", (req, res) => {
  res.send("Hello World!");
});
server.listen(8080, () => {
  console.log("Listening to port 8080");
});
You can find this code in the npm repositoriy for the ws package.
Remember, you need to keep the server active. Otherwise, clients won’t be able to connect.
Now that our server is running successfully, it’s time to create our React Native app.
At the top, we’ll create a horizontal bar to show connection or disconnection notifications as well as errors. At the bottom, we’ll place an input field and a submit button to send messages through WebSockets. The rest of the middle area will be used to display the list of messages received from the server.
It’s a broadcast app, so any message sent from any device will be broadcasted to all.
Let’s check out the code:
import * as React from 'react';
import { Text, View, StyleSheet, TextInput, Button, ScrollView } from 'react-native';
export default function App() {
  const [serverState, setServerState] = React.useState('Loading...');
  const [messageText, setMessageText] = React.useState('');
  const [disableButton, setDisableButton] = React.useState(true);
  const [inputFieldEmpty, setInputFieldEmpty] = React.useState(true);
  const [serverMessages, setServerMessages] = React.useState([]);
  var ws = React.useRef(new WebSocket('ws://w567l.sse.codesandbox.io/')).current;
  React.useEffect(() => {
    const serverMessagesList = [];
    ws.onopen = () => {
      setServerState('Connected to the server')
      setDisableButton(false);
    };
    ws.onclose = (e) => {
      setServerState('Disconnected. Check internet or server.')
      setDisableButton(true);
    };
    ws.onerror = (e) => {
      setServerState(e.message);
    };
    ws.onmessage = (e) => {
      serverMessagesList.push(e.data);
      setServerMessages([...serverMessagesList])
    };
  }, [])
  const submitMessage = () => {
    ws.send(messageText);
    setMessageText('')
    setInputFieldEmpty(true)
  }
  return (
    <View style={styles.container}
      <View style={{
        height: 30,
        backgroundColor: '#eeceff',
        padding: 5
      }}>
        <Text>{serverState}</Text>
      </View>
      <View style={{
        backgroundColor: '#ffeece',
        padding: 5,
        flexGrow: 1
      }}>
        <ScrollView>
          {
            serverMessages.map((item, ind) => {
              return (
                <Text key={ind}>{item}</Text>
              )
            })
          }
        </ScrollView>
      </View>
      <View style={{
        flexDirection: 'row',
      }}>
        <TextInput style={{
            borderWidth: 1,
            borderColor: 'black',
            flexGrow: 1,
            padding: 5,
          }} 
          placeholder={'Add Message'} 
          onChangeText={text => {
            setMessageText(text)
            setInputFieldEmpty(text.length > 0 ? false : true)  
          }}
          value={messageText}
         />
        <Button
         onPress={submitMessage}
         title={'Submit'} 
         disabled={disableButton || inputFieldEmpty}
        />
      </View>
    </View>
  );
}
const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#ecf0f1',
    paddingTop: 30,
    padding: 8,
  },
});
To summarize in brief, the process for implementing WebSockets in a React Native app is as follows:
wsserverState variable, the middle part displays a text messages stored in the serverMessages array, and the bottom bar has an input field that stores typed messages in the messageText state variabledisableButton and inputFieldEmpty variables. The submit button will be active when both disableButton and inputFieldEmpty are falseuseEffect() hook, we define all the WebSocket functionsonopen function is called. This changes the value of serverState variable to connected to the server and disableButton to false, so the top bar of the app shows the connected messageonclose function is called. This changes the serverState to disconnected message and disableButton to true. At this point, the submit button is no longer active, even if you type a message in the input box, because we can’t send messages to the serveronerror function is called and changes the serverState to that particular error messageonmessage function is called. This will append the received message into the serverMessages arraysubmitMessage message to send the message to the server, which the server broadcasts to all devicesHere, I embedded two instances of this app: one for Android and another for iOS. You can test that the message sent from one device will be shown on both. Verify that the Node.js server we embedded above is running fine and is not in hibernation mode.
If you encounter problems with the above devices, you can run the code here.
In this tutorial, we showed you how easy it is to create WebSockets in a React Native apps. The code will run on both Android and iOS platforms.
We created a simple broadcast app for this particular demonstration, but there is a lot of scope to expand it. For example, you could set IDs to distinguish between clients and align messages sent by the client to the right side and all others to the left side. This will produce a perfect chat app-like look and feel.
You could also create a form to capture details (such as the user’s name) before starting a chat and show the information beside received messages.
Let us know in comments what kinds of things you’ve built in React Native using WebSockets.

LogRocket's Galileo AI watches sessions for you and and surfaces the technical and usability issues holding back your React Native apps.
LogRocket also helps you increase conversion rates and product usage by showing you exactly how users are interacting with your app. LogRocket's product analytics features surface the reasons why users don't complete a particular flow or don't adopt a new feature.
Start proactively monitoring your React Native apps — try LogRocket for free.

Learn how platform engineering helps frontend teams streamline workflows with Backstage, automating builds, documentation, and project management.

Build an AI assistant with Vercel AI Elements, which provides pre-built React components specifically designed for AI applications.

line-clamp to trim lines of textMaster the CSS line-clamp property. Learn how to truncate text lines, ensure cross-browser compatibility, and avoid hidden UX pitfalls when designing modern web layouts.

Discover seven custom React Hooks that will simplify your web development process and make you a faster, better, more efficient developer.
Hey there, want to help make our blog better?
Join LogRocket’s Content Advisory Board. You’ll help inform the type of content we create and get access to exclusive meetups, social accreditation, and swag.
Sign up now
2 Replies to "How to implement WebSockets in React Native"
Great article, thanks 🙂
FYI: The JSX is incorrectly escaped in the example code
Thanks for catching that. We’ve updated the post