react-universal-websocket
react-universal-websocket This library is compatible with both React and React Native, offering powerful and flexible React hooks to simplify the management of WebSocket connections. It features seamless WebSocket integration within your applications, including capabilities like automatic reconnection, offline message queuing, and the ability to share WebSocket connections across components. Additionally, it provides typed support for both TypeScript and Flow, ensuring robust type safety for your projects.
🇨🇳 中文文档
Table of Contents
Installation
To install the useWebSocket hook, you can use npm or yarn:
npm install @gedeagas/react-universal-websocket
Or using Yarn:
yarn add @gedeagas/react-universal-websocket
Usage
Here's a basic example of how to use the useWebSocket hook in a React component:
import React, { useEffect } from 'react';
import { useWebSocket, ReadyState } from '@gedeagas/react-universal-websocket';
const WebSocketExample = () => {
const { sendMessage, lastMessage, readyState } = useWebSocket('ws://example.com/socket');
useEffect(() => {
if (lastMessage !== null) {
console.log('Received message:', lastMessage.data);
}
}, [lastMessage]);
const handleClick = () => {
sendMessage('Hello, server!');
};
const connectionStatus = {
[ReadyState.CONNECTING]: 'Connecting',
[ReadyState.OPEN]: 'Open',
[ReadyState.CLOSING]: 'Closing',
[ReadyState.CLOSED]: 'Closed',
[ReadyState.UNINSTANTIATED]: 'Uninstantiated',
}[readyState];
return (
<div>
<button onClick={handleClick}>Send Message</button>
<p>Connection Status: {connectionStatus}</p>
{lastMessage && <p>Last message: {lastMessage.data}</p>}
</div>
);
};
export default WebSocketExample;
Options
The useWebSocket hook accepts a configuration object with various options to customize the behavior of the WebSocket connection:
queryParams (QueryParams): An object containing query parameters to append to the WebSocket URL.
protocols (string | string[]): A string or array of strings representing the subprotocols.
share (boolean): If true, allows sharing of the WebSocket instance among multiple hooks.
onOpen (function): A callback function for when the WebSocket connection opens.
onClose (function): A callback function for when the WebSocket connection closes.
onMessage (function): A callback function for handling incoming messages.
onError (function): A callback function for handling errors.
onReconnectStop (function): A callback function called when reconnection attempts stop.
shouldReconnect (function): A function that determines whether to attempt reconnection.
reconnectInterval (number | function): The interval between reconnection attempts.
reconnectAttempts (number): The maximum number of reconnection attempts allowed.
filter (function): A function to filter incoming messages.
retryOnError (boolean): If true, retries connection on error.
skipAssert (boolean): If true, skips WebSocket assertion checks.
heartbeat (boolean | HeartbeatOptions): Enables heartbeat messages to keep the connection alive.
Here's a comprehensive documentation for the useWebSocket hook options, along with examples for each. This should help developers understand and utilize the different configuration options available.
queryParams
An object containing query parameters to append to the WebSocket URL.
- Type:
{ [key: string]: string | number }
Example:
const options = {
queryParams: { token: 'abcd1234' },
};
const { sendMessage, lastMessage, readyState } = useWebSocket('ws://example.com/socket', options);
protocols
A string or array of strings representing the subprotocols.
Example:
const options = {
protocols: ['protocolOne', 'protocolTwo'],
};
const { sendMessage, lastMessage, readyState } = useWebSocket('ws://example.com/socket', options);
share
If true, allows sharing of the WebSocket instance among multiple hooks.
- Type:
boolean
- Default:
false
Example:
const options = {
share: true,
};
const { sendMessage, lastMessage, readyState } = useWebSocket('ws://example.com/socket', options);
onOpen
A callback function for when the WebSocket connection opens.
- Type:
(event: WebSocketEventMap["open"]) => void
Example:
const options = {
onOpen: (event) => console.log('Connection opened!', event),
};
const { sendMessage, lastMessage, readyState } = useWebSocket('ws://example.com/socket', options);
onClose
A callback function for when the WebSocket connection closes.
- Type:
(event: WebSocketEventMap["close"]) => void
Example:
const options = {
onClose: (event) => console.log('Connection closed!', event),
};
const { sendMessage, lastMessage, readyState } = useWebSocket('ws://example.com/socket', options);
onMessage
A callback function for handling incoming messages.
- Type:
(event: WebSocketEventMap["message"]) => void
Example:
const options = {
onMessage: (event) => console.log('Message received!', event.data),
};
const { sendMessage, lastMessage, readyState } = useWebSocket('ws://example.com/socket', options);
onError
A callback function for handling errors.
- Type:
(event: WebSocketEventMap["error"]) => void
Example:
const options = {
onError: (event) => console.log('Error occurred!', event),
};
const { sendMessage, lastMessage, readyState } = useWebSocket('ws://example.com/socket', options);
onReconnectStop
A callback function called when reconnection attempts stop.
- Type:
(numAttempts: number) => void
Example:
const options = {
onReconnectStop: (numAttempts) => console.log(`Reconnection stopped after ${numAttempts} attempts`),
};
const { sendMessage, lastMessage, readyState } = useWebSocket('ws://example.com/socket', options);
shouldReconnect
A function that determines whether to attempt reconnection.
- Type:
(event: WebSocketEventMap["close"]) => boolean
Example:
const options = {
shouldReconnect: (event) => true,
};
const { sendMessage, lastMessage, readyState } = useWebSocket('ws://example.com/socket', options);
reconnectInterval
The interval between reconnection attempts.
- Type:
number | (lastAttemptNumber: number) => number
Example:
const options = {
reconnectInterval: 5000,
};
const { sendMessage, lastMessage, readyState } = useWebSocket('ws://example.com/socket', options);
reconnectAttempts
The maximum number of reconnection attempts allowed.
Example:
const options = {
reconnectAttempts: 3,
};
const { sendMessage, lastMessage, readyState } = useWebSocket('ws://example.com/socket', options);
filter
A function to filter incoming messages.
- Type:
(message: WebSocketEventMap["message"]) => boolean
Example:
const options = {
filter: (message) => message.data !== 'ignore',
};
const { sendMessage, lastMessage, readyState } = useWebSocket('ws://example.com/socket', options);
retryOnError
If true, retries connection on error.
- Type:
boolean
- Default:
false
Example:
const options = {
retryOnError: true,
};
const { sendMessage, lastMessage, readyState } = useWebSocket('ws://example.com/socket', options);
skipAssert
If true, skips WebSocket assertion checks.
- Type:
boolean
- Default:
false
Example:
const options = {
skipAssert: true,
};
const { sendMessage, lastMessage, readyState } = useWebSocket('ws://example.com/socket', options);
heartbeat
Enables heartbeat messages to keep the connection alive.
- Type:
boolean | HeartbeatOptions
Example:
const options = {
heartbeat: {
message: 'ping',
returnMessage: 'pong',
timeout: 3000,
interval: 10000,
},
};
const { sendMessage, lastMessage, readyState } = useWebSocket('ws://example.com/socket', options);
Complete Usage Example
Here’s a complete example using several options together:
import useWebSocket from 'react-use-websocket';
function App() {
const options = {
queryParams: { token: 'abcd1234' },
protocols: ['protocolOne', 'protocolTwo'],
share: true,
onOpen: (event) => console.log('Connection opened!', event),
onClose: (event) => console.log('Connection closed!', event),
onMessage: (event) => console.log('Message received!', event.data),
onError: (event) => console.log('Error occurred!', event),
onReconnectStop: (numAttempts) => console.log(`Reconnection stopped after ${numAttempts} attempts`),
shouldReconnect: (event) => true,
reconnectInterval: (attemptNumber) => Math.min(Math.pow(2, attemptNumber) * 1000, 10000),
reconnectAttempts: 10,
filter: (message) => message.data !== 'ignore',
retryOnError: true,
skipAssert: true,
heartbeat: {
message: 'ping',
returnMessage: 'pong',
timeout: 3000,
interval: 10000,
},
};
const { sendMessage, lastMessage, readyState } = useWebSocket('ws://example.com/socket', options);
return (
<div>
<p>Ready State: {readyState}</p>
<p>Last Message: {lastMessage ? lastMessage.data : 'No message yet'}</p>
<button onClick={() => sendMessage('Hello WebSocket!')}>Send Message</button>
</div>
);
}
export default App;
This documentation and the accompanying examples should help you understand and leverage the various options provided by the useWebSocket hook.
API
The useWebSocket hook provides the following API:
sendMessage: A function to send a message to the WebSocket server.
sendJsonMessage: A function to send a JSON message to the WebSocket server.
lastMessage: The last message received from the WebSocket server.
lastJsonMessage: The last parsed JSON message received from the WebSocket server.
readyState: The current state of the WebSocket connection.
getWebSocket: A function to get the current WebSocket instance.
Types
- QueryParams: An object mapping strings or numbers to query parameter keys.
- WebSocketMessage: Types of messages that can be sent:
string, ArrayBuffer, SharedArrayBuffer, Blob, or ArrayBufferView.
- SendMessage: A function type to send WebSocket messages.
- SendJsonMessage: A function type to send JSON messages.
- WebSocketHook: The hook return type, including methods and state properties related to the WebSocket connection.
Advanced Usage
Sharing WebSocket Connections
To share a WebSocket connection among multiple components, set the share option to true. This ensures that a single WebSocket instance is reused, reducing the overhead of multiple connections.
const options = {
share: true,
};
const { sendMessage, lastMessage, readyState } = useWebSocket('ws://example.com/socket', options);
Handling Heartbeats
Heartbeats can keep the connection alive by sending periodic messages. Use the heartbeat option to enable and configure heartbeats:
const options = {
heartbeat: {
message: 'ping',
returnMessage: 'pong',
timeout: 10000,
interval: 30000,
},
};
const { sendMessage, lastMessage, readyState } = useWebSocket('ws://example.com/socket', options);
Custom Reconnection Logic
When dealing with WebSocket connections, it's important to handle reconnections gracefully to ensure reliability. This can be achieved using the shouldReconnect, reconnectInterval, and reconnectAttempts options.
Here's an example of how you can configure these options:
Exponential Backoff
Alternatively, you can provide a function for reconnectInterval that accepts the nth last attempt as a parameter and returns a number. This can be useful for employing more advanced reconnect strategies like Exponential Backoff:
const exponentialBackoffOptions = {
shouldReconnect: (closeEvent) => true,
reconnectAttempts: 10,
reconnectInterval: (attemptNumber) =>
Math.min(Math.pow(2, attemptNumber) * 1000, 10000),
};
const { sendMessage, lastMessage, readyState } = useWebSocket(
'wss://echo.websocket.org',
exponentialBackoffOptions
);
Fibonacci Backoff
Another algorithm for reconnection is the Fibonacci Backoff, which uses the Fibonacci sequence to determine the wait time between reconnections. Here's how you can implement it:
const fibonacciBackoffOptions = {
shouldReconnect: (closeEvent) => true,
reconnectAttempts: 10,
reconnectInterval: (attemptNumber) => {
const fibonacci = (n) => {
if (n <= 1) return 1;
return fibonacci(n - 1) + fibonacci(n - 2);
};
return Math.min(fibonacci(attemptNumber + 1) * 1000, 60000);
},
};
const { sendMessage, lastMessage, readyState } = useWebSocket(
'wss://echo.websocket.org',
fibonacciBackoffOptions
);
By customizing the reconnectInterval function, you can control the reconnection strategy and improve the reliability and performance of your WebSocket connections based on your application's needs.
Acknowledgements
This project is a fork of react-use-websocket and is also inspired by react-native-reconnecting-websocket. We extend our gratitude to the authors and contributors of these projects for their excellent work and inspiration.
Contributing
Contributions are welcome! Please feel free to submit a pull request or open an issue.
- Fork the repository.
- Create a new branch (
git checkout -b feature-branch).
- Commit your changes (
git commit -m 'Add new feature').
- Push to the branch (
git push origin feature-branch).
- Open a pull request.
License
This project is licensed under the MIT License. See the LICENSE file for more information.