@ably/chat
Version:
Ably Chat is a set of purpose-built APIs for a host of chat features enabling you to create 1:1, 1:Many, Many:1 and Many:Many chat rooms for any scale. It is designed to meet a wide range of chat use cases, such as livestreams, in-game communication, cust
59 lines (54 loc) • 1.99 kB
text/typescript
import { useCallback, useEffect, useRef } from 'react';
/**
* The type of a callback function that can be stored in the reference.
*/
type Callback<CallbackArguments extends unknown[]> = (...args: CallbackArguments) => void;
/**
* A hook that creates a reference to an event listener callback function. It is used to stabilize the reference
* across renders, so that listeners don't get unsubscribed and resubscribed on every render when passed in as a prop.
*
* For example, doing this:
*
* ```jsx
* export function MySubscription() {
* useHookWithListener(() => {})
*
* return <div>My Subscription</div>
* }
* ```
*
* Where the `useHookWithListener` hook is defined as:
*
* ```jsx
* export function useHookWithListener(listener) {
* const listenerRef = useEventListenerRef(listener);
* useEffect(() => {
* // Use the listenerRef
* }, [listenerRef]);
* }
* ```
*
* Will ensure that the listener is not unsubscribed and resubscribed on every render (i.e. the useEffect will not be called
* on every render).
*
* We allow for the callback to be undefined, as callbacks in the majority of our hooks are optional. In this instance we return undefined,
* so that subscriptions will be unwound by the useEffect hook that's using them.
* @internal
* @template Arguments - The type of arguments accepted by the callback function.
* @param callback - The callback function to be stored in the reference.
* @returns A static callback function that wraps the provided callback function, or undefined if no callback is provided.
*/
export const useEventListenerRef = <Arguments extends unknown[]>(
callback?: Callback<Arguments>,
): Callback<Arguments> | undefined => {
const ref = useRef<Callback<Arguments> | undefined>(callback);
useEffect(() => {
ref.current = callback;
});
const returnVal = useCallback((...args: Arguments) => {
if (ref.current) {
ref.current(...args);
}
}, []);
return callback ? returnVal : undefined;
};