Open karimcambridge opened 4 months ago
This question has been asked before (see #37). I didn't understand it then and I don't understand it now. Could you be more specific about what you mean?
When the server closes the HTTP connection, react-native-sse will automatically reopen it. But I guess when the server just restarts abruptly, it won't try to reconnect. And I honestly don't see a reason why one would expect it to do that, but maybe I'm missing something?
We need it to automatically reconnect, lets say we restart the servers and clients are online on their mobile device. react-native-sse is not automaticaly reconnecting.
Right now I added a useeffect dependency with my socket.connected
from socket.io to trigger a reconnect and if status
is closed. This is my hook example;
import { useEffect, useRef, useState } from 'react';
import EventSource from 'react-native-sse';
import { getServerApiUrl } from '../../api/config';
type EventSourceConstructor = {
new(url: string, eventSourceInitDict?: EventSourceInit): EventSource
};
export type EventSourceStatus = 'init' | 'open' | 'closed' | 'error';
export type EventSourceEvent = Event & { data: string };
export const useEventSource = (user, serverConnection, withCredentials: boolean = false, ESClass: EventSourceConstructor = EventSource) => {
const source = useRef<EventSource | null>(null);
const [status, setStatus] = useState<EventSourceStatus>('init');
useEffect(() => {
if(user && status === 'closed') {
const es = new ESClass(getServerApiUrl() + '/v1/sse/rider/' + user?.id, { withCredentials });
source.current = es;
es.addEventListener('open', () => {
setStatus('open');
console.log('[sse]: connected to ' + getServerApiUrl() + '/v1/sse/rider/' + user.id);
});
es.addEventListener('error', () => {
setStatus('error');
console.log('[sse; error]: connecting to ' + getServerApiUrl() + '/v1/sse/rider/' + user.id);
});
return () => {
source.current = null;
es.removeAllEventListeners();
es.close();
};
}
setStatus('closed');
return undefined;
}, [serverConnection, withCredentials, ESClass]);
return [source.current, status] as const;
};
export function useEventSourceListener(
source: EventSource | null,
types: string[],
listener: (e: EventSourceEvent) => void,
dependencies: any[] = []
) {
useEffect(() => {
if(source) {
types.forEach((type) => source.addEventListener(type, listener as any));
return () => types.forEach((type) => source.removeEventListener(type, listener as any));
}
return undefined;
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [source, ...dependencies]);
}
You could simply add logic to automatically reconnect when no SSE event messages come in for x seconds, e.g. using setTimeout. That would usually imply that the connection is dead.
Maybe there would also be a way to handle this in the react-native-sse library itself, but I'm not sure about that.
would probably need to implement a heartbeat, it can work but unnecessary load.
i thought sses could detect when they lose connection, like we should have the readyState
exposed for us to read.
i thought sses could detect when they lose connection, like we should have the
readyState
exposed for us to read.
We already do an automatic reconnect when the readyState switches to DONE. I think the problem is that the client doesn't event receive a new readyState when the server is abruptly shut down. Thus, there is no direct way for the client to know that the connection is gone. If you find one, please let us know.
when my server restarts this doesn't seem to reestablish my connection, how do I detect that the connection was closed?