diff --git a/src/platform/react-hooks/src/hooks/usePresence.ts b/src/platform/react-hooks/src/hooks/usePresence.ts index ff474271a..eebf541bd 100644 --- a/src/platform/react-hooks/src/hooks/usePresence.ts +++ b/src/platform/react-hooks/src/hooks/usePresence.ts @@ -1,5 +1,5 @@ import type * as Ably from 'ably'; -import { useCallback, useEffect } from 'react'; +import { useCallback, useEffect, useMemo, useRef, useState } from 'react'; import { ChannelParameters } from '../AblyReactHooks.js'; import { useAbly } from './useAbly.js'; import { useChannelInstance } from './useChannelInstance.js'; @@ -27,26 +27,29 @@ export function usePresence( const { channel } = useChannelInstance(params.id, params.channelName); const { connectionError, channelError } = useStateErrors(params); - const onMount = async () => { + const onMount = useCallback(async () => { await channel.presence.enter(messageOrPresenceObject); - }; + // don't add messageOrPresenceObject to dependency list, since it will most likely cause an infinite loop of updates, + // in cases when user calls this hook with an object literal instead of a state or memoized object. + // it does however prevent us from re-entering presence with new data automatically if it changes. + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [channel.presence]); - const onUnmount = () => { + const onUnmount = useCallback(() => { // if connection is in one of inactive states, leave call will produce exception if (channel.state === 'attached' && !INACTIVE_CONNECTION_STATES.includes(ably.connection.state)) { channel.presence.leave(); } - }; + }, [channel, ably.connection.state]); - const useEffectHook = () => { - if (!skip) onMount(); + useEffect(() => { + if (skip) return; + + onMount(); return () => { onUnmount(); }; - }; - - // eslint-disable-next-line react-hooks/exhaustive-deps - useEffect(useEffectHook, [skip]); + }, [skip, onMount, onUnmount]); const updateStatus = useCallback( (messageOrPresenceObject: T) => {