import React, { useEffect, useState, useMemo } from "react" import Echo from "laravel-echo" import Pusher from "pusher-js" /** * Pusher configuration */ const pusherConfig = { key: '', cluster: '', // auth endpoint for private channels // e.g. for Laravel https://example.com/api/broadcasting/auth authEndpoint: '' } /** * Context for Channels */ type TChannels = Echo | undefined const ChannelsContext = React.createContext(undefined) /** * Channel Context Provider */ export function ChannelsProvider({ children, authUser, authToken }: { children: React.ReactNode, authUser?: any authToken?: string }) { const [channels, setChannels] = useState(undefined) useEffect(() => { const channels = getChannels(pusherConfig, authToken); setChannels(channels) return () => { // disconnect from server and reset the channels channels.disconnect() setChannels(undefined) } }, [authUser, authToken]) return ( {children} ) } /** * Hook to use the channels provided via context */ export function useChannels() { const channels = React.useContext(ChannelsContext) return channels } /** * Use private channels * It simple return the useChannels with authenticated user bindings */ export function usePrivateChannels (authUserId: any) { const channels = useChannels() return useMemo(() => { return channels && channels.private("users." + authUserId) }, [channels, authUserId]) } /** * Get the channels */ function getChannels(pusherConfig: typeof pusherConfig, authToken?: string) { const client = new Pusher(pusherConfig.key, { cluster: pusherConfig.cluster, forceTLS: true, authEndpoint: pusherConfig.authEndpoint, auth: authToken ? { headers: { // pass the authorization token when using private channels Authorization: `Bearer ${authToken}`, }, }: undefined, }) const channels = new Echo({ broadcaster: "pusher", client: client, }) return channels }