Skip to main content
Version: v8.0.0

useListener

Read the API Reference »

The useListener hook is your main tool for listening to real-time events from a server in React components. It hooks into the Socket adapter and starts listening for a given event when a component is mounted.

Purpose
  1. Real-time event handling: Listen to server-sent events without manual setup.
  2. Automatic lifecycle management: Manages socket connections when the component mounts and unmounts.
  3. Reactive data updates: Provides the latest data from the server as it arrives.
  4. Connection state tracking: Exposes connected and connecting states to build responsive UIs.
  5. Helper event hooks: Offers onEvent, onError, and onReconnecting for handling specific socket events.

If you intend to send events to the server, we recommend choosing the useEmitter hook.


Quick Start​

To use useListener, provide a Listener instance. The hook automatically listens for events and returns the latest data, timestamp, and connection status.

First, create a Listener instance using your socket client.

Creating a listener
import { socketInstance } from "./socket";

export const onChatMessage = socketInstance.createListener<ChatMessageType>()({
topic: "chat-message",
});

Now, use it in your component to listen for new messages. The onEvent helper hook lets you react to incoming data and update your component's state.

Listening to chat messages
import { useListener } from "@hyper-fetch/react";
import { onChatMessage } from "./api/socket";

function App() {
const [messages, setMessages] = useState([]);
const { data, connected, connecting, onEvent, onError, onReconnecting } = useListener(onChatMessage);

onEvent(({ data: message }) => {
if (message) {
setMessages((prev) => [...prev, message]);
}
});

if (!connected && connecting) {
return <CircularProgress />;
}

return (
<Card>
<div className="font-bold mb-2">Chat Room</div>
<div className="flex flex-col gap-2 p-4 min-h-[200px] bg-gray-50/50 dark:bg-gray-900/50 rounded-lg">
{!messages.length && <div className="text-center text-gray-500">No messages yet.</div>}
{messages.map((message, i) => (
<div key={i} className="bg-white dark:bg-gray-800 p-2 rounded-md shadow-sm">
{message.text}
</div>
))}
</div>
</Card>
);
}

Event Handlers​

useListener provides a set of event handler hooks to manage the socket lifecycle and react to events without cluttering your component's rendering logic.

  1. onEvent: Fires whenever a new event is received from the server.
  2. onError: Fires when a connection or subscription error occurs.
  3. onConnected: Fires when the socket connection is successfully opened.
  4. onDisconnected: Fires when the socket connection is closed.
  5. onConnecting: Fires when the socket is connecting.
  6. onReconnecting: Fires when the socket is attempting to reconnect.
  7. onReconnectingFailed: Fires when the socket fails to reconnect.
Using event handlers
import { useListener } from "@hyper-fetch/react";
import { onChatMessage } from "./api/socket";

function App() {
const [messages, setMessages] = useState([]);
const { onEvent, onError, onConnected, onDisconnected, onConnecting, onReconnecting, onReconnectingFailed } =
useListener(onChatMessage);

onEvent(({ data: message }) => {
toast({ type: "success", message: `New message: ${message.text}` });
setMessages((prev) => [...prev, message]);
});

onError((error) => {
toast({ type: "error", message: `Connection error: ${error.message}` });
});

onConnected(() => {
toast({ type: "info", message: "Socket connection opened." });
});

onDisconnected(() => {
toast({ type: "warning", message: "Socket connection closed." });
});

onConnecting(() => {
toast({ type: "info", message: "Socket is connecting." });
});

onReconnecting(({ attempts }) => {
toast({ type: "warning", message: `Reconnecting... (attempt ${attempts})` });
});

onReconnectingFailed(({ attempts }) => {
toast({ type: "error", message: `Reconnecting failed after ${attempts} attempts.` });
});

return (
<Card>
<div className="font-bold mb-2">Chat Room</div>
<div className="flex flex-col gap-2 p-4 min-h-[200px] bg-gray-50/50 dark:bg-gray-900/50 rounded-lg">
{messages.map((message, i) => (
<div key={i} className="bg-white dark:bg-gray-800 p-2 rounded-md shadow-sm">
{message.text}
</div>
))}
</div>
</Card>
);
}

Throttling & Batching​

Every delivered message is a state update, so a fast stream means fast re-rendering. Instead of throttling inside the component, configure a delivery strategy on the listener. useListener needs no options for this - it simply receives fewer, better-shaped updates, and data follows the delivered type.

Sampling - one render per frame at most
export const onPrice = socket.createListener<Price>()({
topic: "prices",
delivery: { strategy: "latest", interval: 16 },
});

function PriceTicker() {
const { data } = useListener(onPrice); // data: Price | null
return <span>{data?.value}</span>;
}
Batching - arrays, one state update per window
export const onTrade = socket.createListener<Trade>()({
topic: "trades",
delivery: { strategy: "batch", interval: 100 },
});

function TradeLog() {
const [trades, setTrades] = useState<Trade[]>([]);
const { onEvent } = useListener(onTrade); // data: Trade[] | null

onEvent(({ data }) => {
setTrades((previous) => [...previous, ...data]);
});
// ...
}

To let the user change the rate, memoize a setDelivery clone - the hook re-subscribes when the delivery changes:

const live = useMemo(() => onPrice.setDelivery({ strategy: "latest", interval: rate }), [rate]);
const { data } = useListener(live);
Custom strategies

Preset objects are compared by value and can be written inline. Custom strategy functions are compared by identity - define them at module level, or the hook will re-subscribe on every render. See the React Throttling & Batching guide.


Options​

Configuration options for useListener must be provided as the second parameter.

const { ... } = useListener(listener, {
disabled: false,
// ... and more
});

Below is a full list of available options.

UseListenerOptionsType
Name Type Description
dependencyTracking
boolean
When true (default), only re-renders when accessed state properties change

UseListenerOptionsType API Reference
Learn more about the useListener hook options.

State and Methods​

The useListener hook returns an object containing the socket's state and helper methods.

const values = useListener(listener);

useListener
Name Type Description
connected
boolean
connecting
boolean
data
null | ExtractListenerDeliveredType<ListenerType>
extra
null | ExtractSocketExtraType<ListenerType[socket]>
timestamp
null | number
clearState
() => void
listen
() => void
onConnected
(callback: VoidFunction) => void
onConnecting
(callback: VoidFunction) => void
onDisconnected
(callback: VoidFunction) => void
onError
<ErrorType>(callback: (event: ErrorType) => void) => void
onEvent
(callback: (response: { data: ExtractListenerDeliveredType<ListenerType>; extra: Record<string, any> }) => void) => void
onReconnecting
(callback: (data: { attempts: number }) => void) => void
onReconnectingFailed
(callback: (data: { attempts: number }) => void) => void
setConnected
(connected: boolean) => void
setConnecting
(connecting: boolean) => void
setData
(data: null | ExtractListenerDeliveredType<ListenerType>) => void
setExtra
(extra: null | ExtractSocketExtraType<ListenerType[socket]>) => void
setTimestamp
(timestamp: null | number) => void