/ client / src / components / liveify.ts
liveify.ts
 1  import { LiveEvent } from "@refinedev/core";
 2  import { useEffect, useState } from "react";
 3  import { getAPIURL } from "../utils/url";
 4  import liveProvider from "./liveProvider";
 5  
 6  const liveProviderInstance = liveProvider(getAPIURL());
 7  
 8  /**
 9   * Hook that subscribes to live updates for the items in the dataSource
10   * @param dataSource Original dataSource
11   * @returns dataSource that is updated with live data
12   */
13  export function useLiveify<Data extends { id: number }>(
14    resource: string,
15    dataSource: Data[],
16    // eslint-disable-next-line @typescript-eslint/no-explicit-any
17    transformPayload: (payload: any) => Data,
18  ) {
19    // New state that holds the dataSource with updated values from the live provider
20    const [updatedDataSource, setUpdatedDataSource] = useState<Data[]>(dataSource);
21  
22    // If the original dataSource changes, update the updatedDataSource
23    useEffect(() => {
24      setUpdatedDataSource(dataSource);
25    }, [dataSource]);
26  
27    // Subscribe to changes for all items in the dataSource
28    useEffect(() => {
29      const itemIds = dataSource.map((item) => item.id);
30  
31      const subscription = liveProviderInstance?.subscribe({
32        channel: `${resource}-list`,
33        params: {
34          resource: resource,
35          ids: itemIds,
36          subscriptionType: "useList",
37        },
38        types: ["update"],
39        callback: (event: LiveEvent) => {
40          setUpdatedDataSource((prev) =>
41            prev.map((item) => {
42              return item.id === event.payload.data.id ? transformPayload(event.payload.data) : item;
43            }),
44          );
45        },
46      });
47  
48      // Unsubscribe when the component unmounts
49      return () => {
50        if (subscription) {
51          liveProviderInstance?.unsubscribe(subscription);
52        }
53      };
54    }, [resource, dataSource, transformPayload]);
55  
56    return updatedDataSource;
57  }