Hone logo
Hone
Problems

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, or null if 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 ready state should be false.
  • Upon successful connection, ready should become true.
  • Calling send should send the provided message to the server.
  • Receiving a message from the server should trigger the receive callback.
  • Closing the WebSocket connection should set ready to false.
  • Errors during connection or communication should be reflected in the error state.
  • 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 url parameter must be a valid WebSocket URL string.
  • The receiveCallback function must accept a string as an argument.
  • The send function must accept a string as an argument.
  • The reconnectInterval should default to 1000ms if not provided.
  • The reconnectAttempts should 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 useEffect to manage the WebSocket connection lifecycle.
  • Use useState to manage the ready, 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 receive function is a wrapper around the provided receiveCallback. It should simply call the callback with the received message.
  • The close function should explicitly close the WebSocket connection.
  • Consider using a library like use-websocket as inspiration, but implement the logic yourself. Do not directly copy code from external libraries.
Loading editor...
typescript