useSubscription
hook
React Query
Background
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.
General enough solution
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.
Installation
NPM
npm install react-query-subscription react react-query@3 rxjs@7
or
yarn add react-query-subscription react react-query@3 rxjs@7
Use cases
Subscribe to WebSocket
TODO
Subscribe to Event source
import { QueryClientProvider, QueryClient } from 'react-query';
import { ReactQueryDevtools } from 'react-query/devtools';
import { useSubscription, eventSource$ } from 'react-query-subscription';
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',
() => 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>;
}
graphql-ws
GraphQL subscription using 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>;
}
Contributors ✨
Thanks goes to these wonderful people (emoji key):
Katarina Anton 💻 🤔 🚧 |
Jacob Cable 💻 🤔 |
This project follows the all-contributors specification. Contributions of any kind welcome!