Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ React Hook designed to provide robust WebSocket integrations to your React Compo

Pull requests welcomed!

## ESM-only package

Starting with this version, `react-use-websocket` is published as ESM-only. Use `import` syntax when consuming the package. CommonJS `require('react-use-websocket')` is not supported.

## New in 4.0.0

- `react-use-websocket` now supports (and depends on) React 18. If you are not ready to upgrade to React 18, please install version `3.0.0`:
Expand Down
26 changes: 23 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,22 @@
"name": "react-use-websocket",
"version": "4.13.0",
"description": "React Hook for WebSocket communication",
"type": "module",
"main": "./dist/index.js",
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.js"
}
},
"files": [
"src",
"dist"
],
"scripts": {
"test": "cross-env node_modules/.bin/jest --verbose --no-cache",
"clear-dist": "cross-env rm -rf dist/",
"compile": "cross-env node_modules/.bin/tsc -p .",
"compile": "cross-env node_modules/.bin/tsc -p tsconfig.build.json",
"push": "cross-env npm run test && npm run clear-dist && npm run compile && npm publish"
},
"repository": {
Expand Down Expand Up @@ -42,15 +49,28 @@
"typescript": "^5.6.2"
},
"jest": {
"preset": "ts-jest",
"preset": "ts-jest/presets/default-esm",
"clearMocks": true,
"coverageDirectory": "coverage",
"testEnvironment": "jsdom",
"extensionsToTreatAsEsm": [
".ts",
".tsx"
],
"testMatch": [
"<rootDir>/src/lib/**/*.test.(ts|tsx)"
],
"transform": {
"^.+\\.(ts|tsx)?$": "ts-jest"
"^.+\\.(ts|tsx)?$": [
"ts-jest",
{
"useESM": true,
"tsconfig": "tsconfig.test.json"
}
]
},
"moduleNameMapper": {
"^(\\.{1,2}/.*)\\.js$": "$1"
},
"setupFiles": [
"./__test__/configJSDom.ts"
Expand Down
12 changes: 6 additions & 6 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
export { useWebSocket as default } from './lib/use-websocket';
export { useWebSocket as default } from './lib/use-websocket.js';

export { SendMessage, Options } from './lib/types';
export { SendMessage, Options } from './lib/types.js';

export { useSocketIO } from './lib/use-socket-io';
export { useSocketIO } from './lib/use-socket-io.js';

export { ReadyState } from './lib/constants';
export { ReadyState } from './lib/constants.js';

export { useEventSource } from './lib/use-event-source';
export { useEventSource } from './lib/use-event-source.js';

export { resetGlobalState } from './lib/util';
export { resetGlobalState } from './lib/util.js';
6 changes: 3 additions & 3 deletions src/lib/attach-listener.test.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { MutableRefObject } from 'react';
import { attachListeners } from './attach-listener';
import { attachListeners } from './attach-listener.js';
import WS from "jest-websocket-mock";
import { Options } from './types';
import { ReadyState } from './constants';
import { Options } from './types.js';
import { ReadyState } from './constants.js';

let server: WS;

Expand Down
10 changes: 5 additions & 5 deletions src/lib/attach-listener.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { MutableRefObject } from 'react';
import { setUpSocketIOPing } from './socket-io';
import { heartbeat } from './heartbeat';
import { setUpSocketIOPing } from './socket-io.js';
import { heartbeat } from './heartbeat.js';
import {
DEFAULT_RECONNECT_LIMIT,
DEFAULT_RECONNECT_INTERVAL_MS,
ReadyState,
isEventSourceSupported,
} from './constants';
import { Options, SendMessage, WebSocketLike } from './types';
import { assertIsWebSocket } from './util';
} from './constants.js';
import { Options, SendMessage, WebSocketLike } from './types.js';
import { assertIsWebSocket } from './util.js';

export interface Setters {
setLastMessage: (message: WebSocketEventMap['message']) => void;
Expand Down
10 changes: 5 additions & 5 deletions src/lib/attach-shared-listeners.test.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { MutableRefObject } from 'react';
import { attachSharedListeners } from './attach-shared-listeners';
import { attachSharedListeners } from './attach-shared-listeners.js';
import WS from "jest-websocket-mock";
import { Options, Subscriber } from './types';
import { ReadyState } from './constants';
import { sharedWebSockets } from './globals';
import { addSubscriber, removeSubscriber, getSubscribers, hasSubscribers } from './manage-subscribers';
import { Options, Subscriber } from './types.js';
import { ReadyState } from './constants.js';
import { sharedWebSockets } from './globals.js';
import { addSubscriber, removeSubscriber, getSubscribers, hasSubscribers } from './manage-subscribers.js';

let server: WS;
const URL = 'ws://localhost:1234';
Expand Down
12 changes: 6 additions & 6 deletions src/lib/attach-shared-listeners.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { sharedWebSockets } from './globals';
import { DEFAULT_RECONNECT_LIMIT, DEFAULT_RECONNECT_INTERVAL_MS, ReadyState, isEventSourceSupported } from './constants';
import { getSubscribers } from './manage-subscribers';
import { sharedWebSockets } from './globals.js';
import { DEFAULT_RECONNECT_LIMIT, DEFAULT_RECONNECT_INTERVAL_MS, ReadyState, isEventSourceSupported } from './constants.js';
import { getSubscribers } from './manage-subscribers.js';
import { MutableRefObject } from 'react';
import { HeartbeatOptions, Options, SendMessage, WebSocketLike } from './types';
import { setUpSocketIOPing } from './socket-io';
import { heartbeat } from './heartbeat';
import { HeartbeatOptions, Options, SendMessage, WebSocketLike } from './types.js';
import { setUpSocketIOPing } from './socket-io.js';
import { heartbeat } from './heartbeat.js';

const bindMessageHandler = (
webSocketInstance: WebSocketLike,
Expand Down
2 changes: 1 addition & 1 deletion src/lib/constants.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { EventSourceEventHandlers, EventSourceOptions } from "./types";
import { EventSourceEventHandlers, EventSourceOptions } from "./types.js";

const MILLISECONDS = 1;
const SECONDS = 1000 * MILLISECONDS;
Expand Down
6 changes: 3 additions & 3 deletions src/lib/create-or-join.test.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { MutableRefObject } from 'react';
import { createOrJoinSocket } from './create-or-join';
import { createOrJoinSocket } from './create-or-join.js';
import WS from "jest-websocket-mock";
import { Options } from './types';
import { removeSubscriber, getSubscribers, hasSubscribers } from './manage-subscribers';
import { Options } from './types.js';
import { removeSubscriber, getSubscribers, hasSubscribers } from './manage-subscribers.js';

let server: WS;
const URL = 'ws://localhost:1234';
Expand Down
12 changes: 6 additions & 6 deletions src/lib/create-or-join.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { MutableRefObject } from 'react';
import { sharedWebSockets } from './globals';
import { Options, SendMessage, Subscriber, WebSocketLike } from './types';
import { isEventSourceSupported, ReadyState, isReactNative } from './constants';
import { attachListeners } from './attach-listener';
import { attachSharedListeners } from './attach-shared-listeners';
import { addSubscriber, removeSubscriber, hasSubscribers } from './manage-subscribers';
import { sharedWebSockets } from './globals.js';
import { Options, SendMessage, Subscriber, WebSocketLike } from './types.js';
import { isEventSourceSupported, ReadyState, isReactNative } from './constants.js';
import { attachListeners } from './attach-listener.js';
import { attachSharedListeners } from './attach-shared-listeners.js';
import { addSubscriber, removeSubscriber, hasSubscribers } from './manage-subscribers.js';

//TODO ensure that all onClose callbacks are called

Expand Down
4 changes: 2 additions & 2 deletions src/lib/get-url.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { MutableRefObject } from 'react';
import { getUrl } from './get-url';
import { Options } from './types';
import { getUrl } from './get-url.js';
import { Options } from './types.js';

let optionRef: MutableRefObject<Options>;

Expand Down
6 changes: 3 additions & 3 deletions src/lib/get-url.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { MutableRefObject } from 'react';
import { parseSocketIOUrl, appendQueryParams } from './socket-io';
import { Options } from './types';
import { DEFAULT_RECONNECT_INTERVAL_MS, DEFAULT_RECONNECT_LIMIT } from './constants';
import { parseSocketIOUrl, appendQueryParams } from './socket-io.js';
import { Options } from './types.js';
import { DEFAULT_RECONNECT_INTERVAL_MS, DEFAULT_RECONNECT_LIMIT } from './constants.js';

const waitFor = (duration: number) => new Promise(resolve => window.setTimeout(resolve, duration));

Expand Down
4 changes: 2 additions & 2 deletions src/lib/globals.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { sharedWebSockets, resetWebSockets } from './globals';
import { WebSocketLike } from './types';
import { sharedWebSockets, resetWebSockets } from './globals.js';
import { WebSocketLike } from './types.js';

const FIRST_URL = 'ws://localhost:1234';
const SECOND_URL = 'ws://localhost:4321';
Expand Down
2 changes: 1 addition & 1 deletion src/lib/globals.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { WebSocketLike } from "./types";
import { WebSocketLike } from "./types.js";

export interface SharedWebSockets {
[url: string]: WebSocketLike;
Expand Down
2 changes: 1 addition & 1 deletion src/lib/heartbeat.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { heartbeat } from "./heartbeat";
import { heartbeat } from "./heartbeat.js";

describe("heartbeat", () => {
let ws: WebSocket;
Expand Down
4 changes: 2 additions & 2 deletions src/lib/heartbeat.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { MutableRefObject } from "react";
import { DEFAULT_HEARTBEAT } from "./constants";
import { HeartbeatOptions } from "./types";
import { DEFAULT_HEARTBEAT } from "./constants.js";
import { HeartbeatOptions } from "./types.js";

function getLastMessageTime(lastMessageTime: MutableRefObject<number> | MutableRefObject<number>[]): number {
if (Array.isArray(lastMessageTime)) {
Expand Down
4 changes: 2 additions & 2 deletions src/lib/manage-subscribers.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import {
addSubscriber,
removeSubscriber,
resetSubscribers,
} from './manage-subscribers';
import { Subscriber } from './types';
} from './manage-subscribers.js';
import { Subscriber } from './types.js';

const URL = 'ws://localhost:1234';
const SECOND_URL = 'ws://localhost:4321'
Expand Down
2 changes: 1 addition & 1 deletion src/lib/manage-subscribers.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Subscriber } from './types';
import { Subscriber } from './types.js';

export type Subscribers = {
[url: string]: Set<Subscriber>,
Expand Down
2 changes: 1 addition & 1 deletion src/lib/proxy.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { websocketWrapper } from './proxy';
import { websocketWrapper } from './proxy.js';
import WS from "jest-websocket-mock";

let server: WS;
Expand Down
4 changes: 2 additions & 2 deletions src/lib/socket-io.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import {
parseSocketIOUrl,
appendQueryParams,
setUpSocketIOPing,
} from './socket-io';
import { SOCKET_IO_PING_CODE } from './constants';
} from './socket-io.js';
import { SOCKET_IO_PING_CODE } from './constants.js';
import WS from "jest-websocket-mock";

let server: WS;
Expand Down
4 changes: 2 additions & 2 deletions src/lib/socket-io.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { SOCKET_IO_PING_INTERVAL, SOCKET_IO_PATH, SOCKET_IO_PING_CODE } from './constants';
import { QueryParams, SendMessage } from './types';
import { SOCKET_IO_PING_INTERVAL, SOCKET_IO_PATH, SOCKET_IO_PING_CODE } from './constants.js';
import { QueryParams, SendMessage } from './types.js';

export const parseSocketIOUrl = (url: string) => {
if (url) {
Expand Down
2 changes: 1 addition & 1 deletion src/lib/types.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { MutableRefObject } from 'react';
import { ReadyState } from './constants';
import { ReadyState } from './constants.js';

export interface QueryParams {
[key: string]: string | number;
Expand Down
6 changes: 3 additions & 3 deletions src/lib/use-event-source.test.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { renderHook, waitFor } from '@testing-library/react';
import { useEventSource } from './use-event-source';
import { useEventSource } from './use-event-source.js';
import WS from "jest-websocket-mock";
import { EventSourceOptions } from './types';
import { DEFAULT_EVENT_SOURCE_OPTIONS } from './constants';
import { EventSourceOptions } from './types.js';
import { DEFAULT_EVENT_SOURCE_OPTIONS } from './constants.js';

let server: WS;
const URL = 'ws://localhost:1234';
Expand Down
6 changes: 3 additions & 3 deletions src/lib/use-event-source.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useEffect, useRef } from 'react'
import { useWebSocket } from './use-websocket'
import { DEFAULT_EVENT_SOURCE_OPTIONS, EMPTY_EVENT_HANDLERS } from './constants'
import { EventSourceOptions, Options, EventSourceHook, EventSourceEventHandlers } from './types';
import { useWebSocket } from './use-websocket.js'
import { DEFAULT_EVENT_SOURCE_OPTIONS, EMPTY_EVENT_HANDLERS } from './constants.js'
import { EventSourceOptions, Options, EventSourceHook, EventSourceEventHandlers } from './types.js';

export const useEventSource = (
url: string | (() => string | Promise<string>) | null,
Expand Down
6 changes: 3 additions & 3 deletions src/lib/use-socket-io.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useMemo } from 'react'
import { useWebSocket } from './use-websocket'
import { DEFAULT_OPTIONS } from './constants'
import { Options, WebSocketHook } from './types';
import { useWebSocket } from './use-websocket.js'
import { DEFAULT_OPTIONS } from './constants.js'
import { Options, WebSocketHook } from './types.js';

export interface SocketIOMessageData<T = unknown> {
type: string,
Expand Down
8 changes: 4 additions & 4 deletions src/lib/use-websocket.test.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { renderHook, waitFor } from '@testing-library/react';
import { useWebSocket } from './use-websocket';
import { useWebSocket } from './use-websocket.js';
import WS from "jest-websocket-mock";
import { Options } from './types';
import { ReadyState } from './constants';
import { parseSocketIOUrl } from './socket-io';
import { Options } from './types.js';
import { ReadyState } from './constants.js';
import { parseSocketIOUrl } from './socket-io.js';

let server: WS;
const URL = 'ws://localhost:1234';
Expand Down
12 changes: 6 additions & 6 deletions src/lib/use-websocket.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { useEffect, useRef, useState, useCallback, useMemo } from 'react';
import { flushSync } from 'react-dom';
import { DEFAULT_OPTIONS, isEventSourceSupported, ReadyState, UNPARSABLE_JSON_OBJECT } from './constants';
import { createOrJoinSocket } from './create-or-join';
import { getUrl } from './get-url';
import websocketWrapper from './proxy';
import { DEFAULT_OPTIONS, isEventSourceSupported, ReadyState, UNPARSABLE_JSON_OBJECT } from './constants.js';
import { createOrJoinSocket } from './create-or-join.js';
import { getUrl } from './get-url.js';
import websocketWrapper from './proxy.js';
import {
Options,
ReadyStateState,
Expand All @@ -12,8 +12,8 @@ import {
WebSocketMessage,
WebSocketHook,
WebSocketLike,
} from './types';
import { assertIsWebSocket } from './util';
} from './types.js';
import { assertIsWebSocket } from './util.js';

export const useWebSocket = <T = unknown>(
url: string | (() => string | Promise<string>) | null,
Expand Down
6 changes: 3 additions & 3 deletions src/lib/util.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { WebSocketLike } from './types';
import { resetWebSockets } from './globals';
import { resetSubscribers } from './manage-subscribers';
import { WebSocketLike } from './types.js';
import { resetWebSockets } from './globals.js';
import { resetSubscribers } from './manage-subscribers.js';

export function assertIsWebSocket (
webSocketInstance: WebSocketLike,
Expand Down
27 changes: 27 additions & 0 deletions tsconfig.base.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"compilerOptions": {
"sourceMap": true,
"esModuleInterop": true,
"target": "es5",
"jsx": "react",
"skipLibCheck": true,
"lib": [
"es2017",
"dom"
],
"strict": true,
"declaration": true,
"baseUrl": ".",
"paths": {
"@lib/*": [
"src/lib/*"
]
}
},
"files": [
"./src/index.ts"
],
"include": [
"src/*"
]
}
Loading