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 }