Create a Reusable useWebSocket Hook in React with TypeScript
This challenge asks you to build a custom React hook, useWebSocket, that simplifies connecting to and managing WebSocket connections within your components. A well-designed useWebSocket hook will encapsulate the complexities of WebSocket management, providing a clean and reusable interface for your React applications to interact with WebSocket servers. This is particularly useful for real-time applications like chat apps, live dashboards, or collaborative tools.
Problem Description
You need to create a React hook named useWebSocket that handles WebSocket connection management. The hook should accept a url (string) as an argument, representing the WebSocket server URL. It should return an object containing the following properties:
ready: A boolean indicating whether the WebSocket connection is open and ready to send/receive messages.send: A function that accepts a message (string) and sends it to the WebSocket server.receive: A function that accepts a message (string) and calls a provided callback function with the message.close: A function that closes the WebSocket connection.error: A string containing any error message encountered during connection or communication, ornullif no error occurred.reconnectInterval: A number representing the interval (in milliseconds) at which the hook attempts to reconnect if the connection is lost. Defaults to 1000ms.reconnectAttempts: A number representing the maximum number of reconnection attempts. Defaults to 5.
The hook should automatically:
- Establish a WebSocket connection when the component mounts.
- Handle connection opening, closing, and errors.
- Provide a mechanism to send messages to the server.
- Provide a mechanism to receive messages from the server.
- Attempt to reconnect if the connection is lost, with a configurable reconnect interval and maximum attempts.
- Clean up the WebSocket connection when the component unmounts.
Expected Behavior:
- On initial mount, the
readystate should befalse. - Upon successful connection,
readyshould becometrue. - Calling
sendshould send the provided message to the server. - Receiving a message from the server should trigger the
receivecallback. - Closing the WebSocket connection should set
readytofalse. - Errors during connection or communication should be reflected in the
errorstate. - Reconnection attempts should occur at the specified interval until successful or the maximum attempts are reached.
Examples
Example 1:
Input: url = "ws://localhost:8080", receiveCallback = (message) => console.log("Received:", message)
Output: { ready: true, send: (message: string) => {}, close: () => {}, receive: (message: string) => {}, error: null, reconnectInterval: 1000, reconnectAttempts: 5 }
Explanation: A successful WebSocket connection is established, and the hook returns an object with functions for sending, receiving, and closing the connection.
Example 2:
Input: url = "ws://invalid-url", receiveCallback = (message) => console.log("Received:", message)
Output: { ready: false, send: (message: string) => {}, close: () => {}, receive: (message: string) => {}, error: "WebSocket connection failed", reconnectInterval: 1000, reconnectAttempts: 5 }
Explanation: The WebSocket connection fails to establish, and the `error` state reflects this. The hook will attempt to reconnect.
Example 3: (Edge Case - Disconnected Connection)
Input: url = "ws://localhost:8080" (connection is initially established, then abruptly closed by the server), receiveCallback = (message) => console.log("Received:", message)
Output: After disconnection and reconnection attempts: { ready: false, send: (message: string) => {}, close: () => {}, receive: (message: string) => {}, error: "Maximum reconnection attempts reached", reconnectInterval: 1000, reconnectAttempts: 5 }
Explanation: The server closes the connection. The hook attempts to reconnect up to the configured `reconnectAttempts`. If reconnection fails, the `error` state is updated.
Constraints
- The
urlparameter must be a valid WebSocket URL string. - The
receiveCallbackfunction must accept a string as an argument. - The
sendfunction must accept a string as an argument. - The
reconnectIntervalshould default to 1000ms if not provided. - The
reconnectAttemptsshould default to 5 if not provided. - The hook should not cause memory leaks. Proper cleanup of the WebSocket connection is essential.
- The hook should handle potential errors gracefully and provide informative error messages.
Notes
- Consider using
useEffectto manage the WebSocket connection lifecycle. - Use
useStateto manage theready,error, and other relevant states. - Implement proper error handling to catch connection errors and message sending failures.
- Think about how to handle reconnection logic and prevent infinite loops.
- The
receivefunction is a wrapper around the providedreceiveCallback. It should simply call the callback with the received message. - The
closefunction should explicitly close the WebSocket connection. - Consider using a library like
use-websocketas inspiration, but implement the logic yourself. Do not directly copy code from external libraries.