Skip to main content
React Native provides a WebSocket implementation that follows the Web API specification. WebSockets enable bidirectional, real-time communication between a client and server.

Constructor

new WebSocket(url: string, protocols?: string | string[], options?: object)
Creates a new WebSocket connection.
url
string
required
The URL to connect to. Must use ws:// or wss:// protocol.
protocols
string | string[]
Optional subprotocol(s) to use. Can be a single string or array of strings.
options
object
Connection options
headers
object
Custom headers to include in the connection request
origin
string
Origin header value

Properties

State Constants

WebSocket.CONNECTING
number
default:"0"
Connection is being established
WebSocket.OPEN
number
default:"1"
Connection is open and ready to communicate
WebSocket.CLOSING
number
default:"2"
Connection is in the process of closing
WebSocket.CLOSED
number
default:"3"
Connection is closed

Instance Properties

readyState
number
Current connection state. One of the state constants above.
url
string
The URL of the WebSocket connection
protocol
string
The subprotocol selected by the server
bufferedAmount
number
Number of bytes queued to be sent
binaryType
'blob' | 'arraybuffer'
Type of binary data received. Can be set to 'blob' or 'arraybuffer'.

Methods

send()

send(data: string | ArrayBuffer | ArrayBufferView | Blob): void
Sends data through the WebSocket connection.
data
string | ArrayBuffer | ArrayBufferView | Blob
required
Data to send:
  • string: Text message
  • ArrayBuffer: Binary data
  • ArrayBufferView: Typed array (Uint8Array, etc.)
  • Blob: Binary large object
Throws INVALID_STATE_ERR if called before connection is open.

close()

close(code?: number, reason?: string): void
Closes the WebSocket connection.
code
number
default:"1000"
Close status code. Default is 1000 (normal closure).Common codes:
  • 1000 - Normal closure
  • 1001 - Going away
  • 1002 - Protocol error
  • 1003 - Unsupported data
  • 1006 - Abnormal closure (no close frame received)
reason
string
Human-readable reason for closing

ping()

ping(): void
Sends a ping frame to the server. Used for keep-alive. Throws INVALID_STATE_ERR if called before connection is open.

Event Handlers

onopen

ws.onopen = (event) => {
  // Connection opened
};
Called when the WebSocket connection is successfully opened.

onmessage

ws.onmessage = (event) => {
  // event.data contains the message
};
Called when a message is received from the server. The event.data can be:
  • string for text messages
  • ArrayBuffer if binaryType is set to 'arraybuffer'
  • Blob if binaryType is set to 'blob'

onerror

ws.onerror = (event) => {
  // Connection error occurred
};
Called when an error occurs.

onclose

ws.onclose = (event) => {
  // event.code contains the close code
  // event.reason contains the close reason
};
Called when the connection is closed. The event object contains:
  • code - Close status code
  • reason - Close reason string

Examples

Basic Connection

const ws = new WebSocket('wss://echo.websocket.org');

ws.onopen = () => {
  console.log('Connected');
  ws.send('Hello Server!');
};

ws.onmessage = (e) => {
  console.log('Received:', e.data);
};

ws.onerror = (e) => {
  console.error('Error:', e.message);
};

ws.onclose = (e) => {
  console.log('Closed:', e.code, e.reason);
};

React Component

import React, {useEffect, useState} from 'react';
import {View, Text, Button, TextInput} from 'react-native';

function WebSocketChat() {
  const [ws, setWs] = useState(null);
  const [message, setMessage] = useState('');
  const [messages, setMessages] = useState([]);
  const [connected, setConnected] = useState(false);

  useEffect(() => {
    const websocket = new WebSocket('wss://echo.websocket.org');

    websocket.onopen = () => {
      console.log('Connected');
      setConnected(true);
    };

    websocket.onmessage = (e) => {
      setMessages(prev => [...prev, `Server: ${e.data}`]);
    };

    websocket.onerror = (e) => {
      console.error('WebSocket error:', e.message);
    };

    websocket.onclose = (e) => {
      console.log('Disconnected:', e.code, e.reason);
      setConnected(false);
    };

    setWs(websocket);

    return () => {
      websocket.close();
    };
  }, []);

  const sendMessage = () => {
    if (ws && message) {
      ws.send(message);
      setMessages(prev => [...prev, `You: ${message}`]);
      setMessage('');
    }
  };

  return (
    <View>
      <Text>Status: {connected ? 'Connected' : 'Disconnected'}</Text>
      {messages.map((msg, i) => (
        <Text key={i}>{msg}</Text>
      ))}
      <TextInput
        value={message}
        onChangeText={setMessage}
        placeholder="Type a message"
      />
      <Button
        title="Send"
        onPress={sendMessage}
        disabled={!connected}
      />
    </View>
  );
}

With Custom Headers

const ws = new WebSocket(
  'wss://api.example.com/socket',
  null,
  {
    headers: {
      Authorization: 'Bearer your-token-here',
      'X-Custom-Header': 'value',
    },
  }
);

Binary Data with ArrayBuffer

const ws = new WebSocket('wss://example.com/binary');
ws.binaryType = 'arraybuffer';

ws.onopen = () => {
  // Send binary data
  const buffer = new ArrayBuffer(4);
  const view = new Uint8Array(buffer);
  view[0] = 1;
  view[1] = 2;
  view[2] = 3;
  view[3] = 4;
  ws.send(buffer);
};

ws.onmessage = (e) => {
  if (e.data instanceof ArrayBuffer) {
    const view = new Uint8Array(e.data);
    console.log('Received binary:', view);
  }
};

Binary Data with Blob

const ws = new WebSocket('wss://example.com/blob');
ws.binaryType = 'blob';

ws.onmessage = async (e) => {
  if (e.data instanceof Blob) {
    const text = await e.data.text();
    console.log('Blob as text:', text);
  }
};

Automatic Reconnection

import React, {useEffect, useRef, useState} from 'react';

function useWebSocket(url, options = {}) {
  const [readyState, setReadyState] = useState(WebSocket.CONNECTING);
  const ws = useRef(null);
  const reconnectTimeout = useRef(null);

  const connect = () => {
    ws.current = new WebSocket(url);

    ws.current.onopen = () => {
      console.log('Connected');
      setReadyState(WebSocket.OPEN);
      if (options.onOpen) options.onOpen();
    };

    ws.current.onmessage = (e) => {
      if (options.onMessage) options.onMessage(e);
    };

    ws.current.onerror = (e) => {
      console.error('Error:', e.message);
      if (options.onError) options.onError(e);
    };

    ws.current.onclose = (e) => {
      console.log('Closed:', e.code, e.reason);
      setReadyState(WebSocket.CLOSED);
      if (options.onClose) options.onClose(e);

      // Attempt to reconnect after 3 seconds
      reconnectTimeout.current = setTimeout(() => {
        console.log('Reconnecting...');
        connect();
      }, 3000);
    };
  };

  useEffect(() => {
    connect();

    return () => {
      if (reconnectTimeout.current) {
        clearTimeout(reconnectTimeout.current);
      }
      if (ws.current) {
        ws.current.close();
      }
    };
  }, [url]);

  const send = (data) => {
    if (ws.current && readyState === WebSocket.OPEN) {
      ws.current.send(data);
    } else {
      console.warn('WebSocket not connected');
    }
  };

  return {readyState, send};
}

// Usage
function MyComponent() {
  const {readyState, send} = useWebSocket('wss://echo.websocket.org', {
    onMessage: (e) => console.log('Message:', e.data),
  });

  return (
    <Button
      title="Send"
      onPress={() => send('Hello!')}
      disabled={readyState !== WebSocket.OPEN}
    />
  );
}

Ping/Keep-Alive

const ws = new WebSocket('wss://example.com');
let pingInterval;

ws.onopen = () => {
  // Send ping every 30 seconds
  pingInterval = setInterval(() => {
    if (ws.readyState === WebSocket.OPEN) {
      ws.ping();
    }
  }, 30000);
};

ws.onclose = () => {
  clearInterval(pingInterval);
};

JSON Messages

const ws = new WebSocket('wss://api.example.com');

ws.onopen = () => {
  // Send JSON data
  const data = {
    type: 'subscribe',
    channel: 'updates',
  };
  ws.send(JSON.stringify(data));
};

ws.onmessage = (e) => {
  try {
    const data = JSON.parse(e.data);
    console.log('Parsed message:', data);
  } catch (error) {
    console.error('Failed to parse JSON:', error);
  }
};

Notes

  • WebSocket follows the browser WebSocket API specification
  • Secure connections (wss://) are recommended for production
  • On iOS, configure App Transport Security to allow non-HTTPS connections if needed
  • Binary data requires setting binaryType property
  • Use ping() for keep-alive on long-lived connections
  • Always clean up WebSocket connections in component unmount
  • Consider using libraries like socket.io-client for advanced features (rooms, automatic reconnection, etc.)
  • Handle reconnection logic for production applications
  • Be mindful of battery usage with persistent connections

Build docs developers (and LLMs) love