While React Query is very feature rich, it misses one thing - support for streams, event emitters, WebSockets etc. This library leverages React Query's useQuery
to provide useSubscription
hook for subscribing to real-time data.
React Query useQuery
's query function is any function which returns a Promise. Similarly, useSubscription
's subscription function is any function which returns an Observable.
npm install react-query-subscription react react-query@3 rxjs@7
or
yarn add react-query-subscription react react-query@3 rxjs@7
Please see examples.
TODO
import { QueryClientProvider, QueryClient } from 'react-query';
import { ReactQueryDevtools } from 'react-query/devtools';
import { useSubscription } from 'react-query-subscription';
import { eventSource$ } from 'rx-event-source';
const queryClient = new QueryClient();
function App() {
return (
<QueryClientProvider client={queryClient}>
<SseExample />
<ReactQueryDevtools initialIsOpen={false} />
</QueryClientProvider>
);
}
function SseExample() {
const { data, isLoading, isError, error } = useSubscription(
'some-key',
// @see https://kaciakmaciak.github.io/rx-event-source/modules.html#eventSource_
() => eventSource$('/api/v1/sse'),
{
// options
}
);
if (isLoading) {
return <div>Loading...</div>;
}
if (isError) {
return (
<div role="alert">
{error?.message || 'Unknown error'}
</div>
);
}
return <div>Data: {JSON.stringify(data)}</div>;
}
See rx-event-source
docs.
GraphQL subscription using graphql-ws
import { QueryClientProvider, QueryClient } from 'react-query';
import { ReactQueryDevtools } from 'react-query/devtools';
import { useSubscription } from 'react-query-subscription';
import { Observable } from 'rxjs';
import { createClient } from 'graphql-ws';
import type { Client, SubscribePayload } from 'graphql-ws';
const queryClient = new QueryClient();
function App() {
return (
<QueryClientProvider client={queryClient}>
<GraphQlWsExample postId="abc123" />
<ReactQueryDevtools initialIsOpen={false} />
</QueryClientProvider>
);
}
const client = createClient({ url: 'wss://example.com/graphql' });
/**
* @see https://github.com/enisdenjo/graphql-ws#observable
*/
export function fromWsClientSubscription<TData = Record<string, unknown>>(
client: Client,
payload: SubscribePayload
) {
return new Observable<TData | null>((observer) =>
client.subscribe<TData>(payload, {
next: (data) => observer.next(data.data),
error: (err) => observer.error(err),
complete: () => observer.complete(),
})
);
}
interface Props {
postId: string;
}
interface Comment {
id: string;
content: string;
}
function GraphQlWsExample({ postId }: Props) {
const { data, isLoading, isError, error } = useSubscription(
'some-key',
() => fromWsClientSubscription<{ comments: Array<Comment> }>({
query: `
subscription Comments($postId: ID!) {
comments(postId: $postId) {
id
content
}
}
`,
variables: {
postId,
},
}),
{
// options
}
);
if (isLoading) {
return <div>Loading...</div>;
}
if (isError) {
return (
<div role="alert">
{error?.message || 'Unknown error'}
</div>
);
}
return <div>Data: {JSON.stringify(data?.comments)}</div>;
}
Thanks goes to these wonderful people (emoji key):
Katarina Anton π» π€ π§ |
Jacob Cable π» π€ |
This project follows the all-contributors specification. Contributions of any kind welcome!