Skip to main content
Version: 5.x.x

Socket Listener


Listener is a class that creates a template for receiving events from server. Its strength is its strict and predictable data structure which together with typescript gives a lot of confidence while developing data exchange features.

To use the listener we need to trigger the listen method with provided callback.


  • Configures events listeners templates
  • Standardizes the system’s data schema
  • Listen to server events


Listener should be initialized from the Socket instance with createListener method. This passes a shared reference to the place that manages communication in the application.

import { socket } from "./socket";

export const onChatMessage = socket.createListener<ChatMessageType>()({
endpoint: "chat-message", // endpoint of the event

export const onUserStatusChange = socket.createListener<UserStatusType>()({
endpoint: "status", // endpoint of the event



Use the listen method to start the listening for incoming events.

callback: (message) => {
// message have type ChatMessageType

Remove listener

Use the returned method to stop listening.

const removeEvent = onChatMessage.listen({ callback: (message) => console.log(message) });


removeEvent() // We remove listener

Remove event listeners directly from the adapter

const callback = (message) => console.log(message);
const removeEvent = onChatMessage.listen({ callback });


socket.adapter.listeners.delete(onChatMessage.endpoint) // We remove ALL listeners from given event
socket.adapter.listeners.get(onChatMessage.endpoint).delete(callback) // We remove single listener from given event

Listen to event once

const removeEvent = onChatMessage.listen({
callback: (message) => {
removeEvent(); // We listen only to single event

Listening with onData hook

You can use onData method to listen to all events of given listener. This method is useful when you want to attach some logic to any occurrence of the event. It's additional way of hooking into the listener groups.

export const onNoteChange = socket
endpoint: "notes/:id",
.onData((event) => {
// We will receive all events from given listener,
// no mater of ID, as it will be filled later on while listening

onNoteChange.setParams({ noteId: 1 }).listen(() => {
// some logic

onNoteChange.setParams({ noteId: 2 }).listen(() => {
// some logic

// console.log(event) ===> { noteId: 1, ... }
// console.log(event) ===> { noteId: 2, ... }

Integration with Hyper Fetch

We can use this to make simple integration with Hyper Fetch. We can use onData hook to update the cache with new data from the socket.

// ==> Our core setup
const client = new Client({ url: "http://localhost:3000" });
const getNote = client.createRequest()({
endpoint: "/note/:noteId";

// ==> Our realtime listener

export const onNoteChange = socket.createListener<NoteData>()({
endpoint: "notes",
}).onData((event) => {
const { noteId } = event;

// Fill the params so our cache can find the request in storage
const noteRequest = client.cache.get(getNote.setParams({ noteId }));

// Update the cache
client.cache.update(noteRequest, (prevData) => {
return {...prevData, data: event}


Using methods on a listener is different from other classes in Hyper Fetch. This is to ensure isolation between different uses, which allows you to avoid overwriting previously-prepared listeners and to dynamically generate keys for queues or the cache.


Using any method on listener returns its clone! We don't return a reference!

// ❌ WRONG

const listener = getChatMessageListener;

listener.setOptions({ ... }); // Returns CLONED listener with assigned options

listener.listen(); // Error - no options will be applied
// ✅ Good

const listener = getChatMessageListener;

const listenerWithOptions = listener.setOptions({ ... }); // Returns CLONED listener with assigned options

listenerWithOptions.listen(); // Success - options applied


Configuration options

endpoint: Endpoint;
options: T extends SocketAdapterType<any, any, infer O, any> ? O : never;
params: string extends T ? NegativeTypes : (T extends ${string}:,${infer Param}/,${infer Rest} ? [k in Param | keyof ExtractRouteParams<Rest>]: ParamType : (T extends ${string}:,${infer Param} ? [k in Param]: ParamType : NegativeTypes));