Built and signed on GitHub ActionsBuilt and signed on GitHub Actions
rocket-io
Wrapper for socket.io-client in ReactJs - works for React Native.
This package is using lbundle
as bundler ✨
Install
NPM registry
# npm npm i socket.io-client rocket-io # yarn yarn add socket.io-client rocket-io # bun bun install socket.io-client rocket-io # pnpm pnpm i socket.io-client rocket-io
JSR registry
# deno deno add @mrii/rocket-io # jsr npx jsr add @mrii/rocket-io
Usage
Initialization
Call the createSocketHooks
to get an instance of the hooks with the socket:
socket.io-hooks.ts
import { io } from 'socket.io-client'; import { createSocketHooks } from 'rocket-io'; const socketInstance = io(/* ... */); // exports the hooks export const { socket, useDisconnectOnUnmount, useSocket, useOn, useOnce, useEmit, useImmediateEmit, useEmitEffect, } = createSocketHooks(socketInstance);
Alternative without io
you can pass io
arguments to createSocketHooks
and it will create the socket internally:
socket.io-hooks.ts
export const { /* ... */ } = createSocketHooks(url, options); // or with only options export const { /* ... */ } = createSocketHooks(options);
Alternative without initial socket - Lazy Initialization
you can delay the creating of the socket if you need information from the react tree, use useInitSocket
to initialize it:
socket.io-hooks.ts
export const { useInitSocket, /* ... */ } = createSocketHooks();
Later on in the App
app.tsx
/* ... */ const App: React.FC = () => { /* ... */ useInitSocket('<url>', { auth: { token } }); // if the token isn't ready, or you don't want to initialize the socket yet, pass the `ready` arg useInitSocket('<url>', { auth: { token } }, isReady); /* ... */ };
Using the hooks
component.tsx
/* ... */ export const Component: React.FC = () => { /* ... */ useOn('event', data => { console.log('[event] fired with: ', data); }); useImmediateEmit('event-2', 'event-2 fired immediately'); const emit = useEmit(); /* ... */ return <button onClick={() => emit('event', 'event data')}>emit event</button>; };
TypeScript Support
You can pass your events map to createSocketHooks
to provide you with safe listeners and emission events:
socket.io-hooks.ts
export type EmitEvents = { send_message: (message: string) => void; }; export type ListenEvents = { message: (message: string) => void; }; export const { /* ... */ } = createSocketHooks<EmitEvents, ListenEvents>();
component.tsx
/* ... */ export const Component: React.FC = () => { /* ... */ useOn( /* typed! */ 'message', /* data type is provided! */ data => { console.log('[message] fired with: ', data); } ); useImmediateEmit( /* typed! */ 'send_message', /* emit arguments type is provided! */ 'message' ); };
Examples
Eager Initialization - casual applications
create and export the hooks:
socket.io-hooks.ts
import { createSocketHooks } from 'rocket-io'; // exports the hooks export const { socket, useDisconnectOnUnmount, useSocket, useOn, useOnce, useEmit, useImmediateEmit, useEmitEffect, } = createSocketHooks('<url>', { /* options */ });
disconnect on application unmount:
app.tsx
/* ... */ const App: React.FC = () => { /* ... */ useDisconnectOnUnmount(); /* ... */ };
use the hooks:
component.tsx
/* ... */ export const Component: React.FC = () => { /* ... */ // listen to event useOn('event', data => { console.log('[event] fired with: ', data); }); // listen to event once useOn('ready', () => { console.log('[ready] event fired'); }); // emit event when `Component` mounts useImmediateEmit('event-2', 'event-2 fired immediately'); // emit event when dependencies array changes - similar to `useEffect(, deps)` useEmitEffect([message], 'event-3', 'event-3 fired with new message: ' + message); // get emit function const emit = useEmit(); /* ... */ return <button onClick={() => emit('event', 'event data')}>emit event</button>; };
Lazy Initialization - authorized sockets
create and export the hooks:
socket.io-hooks.ts
import { createSocketHooks } from 'rocket-io'; // exports the hooks export const { useInitSocket, useDisconnectOnUnmount, useSocket, useOn, useOnce, useEmit, useImmediateEmit, useEmitEffect, } = createSocketHooks();
initialize the socket once args is ready:
app.tsx
/* ... */ const App: React.FC = () => { /* ... */ useInitSocket('<url>', { auth: { token } }, typeof token === 'string'); useDisconnectOnUnmount(); /* ... */ };
and then use the hooks normally
Multiple Sockets
you can create two socket hooks by calling createSocketHooks
:
admin-socket-hooks.ts
import { createSocketHooks } from 'rocket-io'; export const adminSocketHooks = createSocketHooks('<admin-url>', { /* admin options */ });
products-socket-hooks.ts
import { createSocketHooks } from 'rocket-io'; export const productsSocketHooks = createSocketHooks('<products-url>', { /* products options */ });
API
socket
the socket in case you initialized it using createSocketHooks
.
type Socket<TListenEvents, TEmitEvents>
.
it will be undefined
in case of Lazy Initialization.
useInitSocket
hook to init your socket in the app in case of Lazy Initialization.
Property | Type | Default | Description | Version |
---|---|---|---|---|
arg0:uri | string |
undefined |
socket uri (io(uri) ) |
0.0.1 |
arg1:options | Partial<ManagerOptions & SocketOptions>? |
undefined |
socket options (io(, options) ) |
0.0.1 |
arg2:start | boolean? |
true |
start initializing the socket | 0.0.1 |
return: void
useDisconnectOnUnmount
hook to disconnect and destroy the socket instance on unmounting, use in your root app if needed.
take no args
return: void
useSocket
hook that returns the instance of the socket.
take no args
return: Socket<TListenEvents, TEmitEvents>
it might return undefined
in case of Lazy Initialization
useOn
hook to listen on every event emission.
Property | Type | Default | Description | Version |
---|---|---|---|---|
arg0:key | string |
undefined |
event key to listen on (socket.on(key) ) |
0.0.1 |
arg1:listener | Function |
undefined |
listener that will will be called when the event fires (socket.on(, listener) ) |
0.0.1 |
return: void
useOnce
hook to listen once on event emission.
Property | Type | Default | Description | Version |
---|---|---|---|---|
arg0:key | string |
undefined |
event key to listen on (socket.once(key) ) |
0.0.1 |
arg1:listener | Function |
undefined |
listener that will will be called when the event fires (socket.once(, listener) ) |
0.0.1 |
return: void
useEmit
hook that return the socket.emit
function, or a lazy emission function in case of Lazy Initialization,
lazy emission function will emit if socket is available, or record event until the socket is available.
take no args.
return: socket.emit
function.
useImmediateEmit
hook to emit an event once.
Property | Type | Default | Description | Version |
---|---|---|---|---|
arg0:key | string |
undefined |
event key to emit (socket.emit(key) ) |
0.0.1 |
...args | unknown[] |
undefined |
extra arguments to emit them (socket.emit(, ...args) ) |
0.0.1 |
return: void
useEmitEffect
hook to emit an event on mount and once the dependency array changes.
Property | Type | Default | Description | Version |
---|---|---|---|---|
arg0:deps | unknown[] |
undefined |
dependency array to listen on (like useEffect(, deps) ) |
0.0.1 |
arg1:key | string |
undefined |
event key to emit (socket.emit(key) ) |
0.0.1 |
...args | unknown[] |
undefined |
extra arguments to emit them (socket.emit(, ...args) ) |
0.0.1 |
return: void
NOTES
-
try to use the hooks (
useEmit
,useOn
, ...) instead of getting thesocket
fromuseSocket
and use it, because there some extra cases handled in those hooks. -
useInitSocket
will not reinitialize the socket in case it's already initialized, utilize the third argumentready
to indicate when you have all of the required properties to start initializing. -
no need to use
useCallback
withuseOn(, cb)
oruseOnce(, cb)
because it's handled internally. -
changing the event name during renders will not affect
useImmediateEmit(ev)
oruseEmitEffect(, ev)
, so if you want such behavior make sure to add it to the deps array usinguseEmitEffect([ev], ev)
.
Add Package
deno add jsr:@mrii/rocket-io
Import symbol
import * as rocket_io from "@mrii/rocket-io";
Import directly with a jsr specifier
import * as rocket_io from "jsr:@mrii/rocket-io";
Add Package
pnpm i jsr:@mrii/rocket-io
pnpm dlx jsr add @mrii/rocket-io
Import symbol
import * as rocket_io from "@mrii/rocket-io";
Add Package
yarn add jsr:@mrii/rocket-io
yarn dlx jsr add @mrii/rocket-io
Import symbol
import * as rocket_io from "@mrii/rocket-io";
Add Package
vlt install jsr:@mrii/rocket-io
Import symbol
import * as rocket_io from "@mrii/rocket-io";
Add Package
npx jsr add @mrii/rocket-io
Import symbol
import * as rocket_io from "@mrii/rocket-io";
Add Package
bunx jsr add @mrii/rocket-io
Import symbol
import * as rocket_io from "@mrii/rocket-io";