Remix > Real-time updates

Real-time updates

Live updates can be extremely useful both for content editors and the regular visitors of your app/website:

  • Content-editors in Preview Mode can see drafts directly in the production website, without having to refresh the page;

  • Visitors can immediately see new content as it gets published, allowing all kinds of real-time interactions with your website/app (ie. live-news coverage).

Inside a Remix project, it's extremely easy to use our Real-time Updates API to perform such changes, as it only involves adding a React hook to your page components.

How to use the useQuerySubscription hook

The react-datocms package exposes a useQuerySubscription hook that makes it trivial to update any Remix page in real-time.

The hook works by streaming any changes present to the response of a GraphQL query directly to the browser, and it a loader responsibility to prepare an object compatible with the options of the hook itself.

The following code shows a complete example that activates real-time updates for any visitor of your website:

import { useQuerySubscription } from "react-datocms";
import { load } from '~/lib/datocms';
const BLOG_POST_QUERY = `query HomePage {
blogPost {
title
}
}`;
export async function loader() {
return {
subscription: {
query: BLOG_POST_QUERY,
initialData: await load(BLOG_POST_QUERY),
token: process.env.DATOCMS_READONLY_TOKEN,
environment: process.env.DATOCMS_ENVIRONMENT,
},
};
}
export default function Home({ subscription }) {
const { data, error, status } = useQuerySubscription(subscription);
const statusMessage = {
connecting: 'Connecting to DatoCMS...',
connected: 'Connected to DatoCMS, receiving live updates!',
closed: 'Connection closed',
};
return (
<div>
<p>Connection status: {statusMessage[status]}</p>
{error && (
<div>
<h1>Error: {error.code}</h1>
<div>{error.message}</div>
{error.response && (
<pre>{JSON.stringify(error.response, null, 2)}</pre>
)}
</div>
)}
{data && (
<div>{JSON.stringify(data, null, 2)}</div>
)}
</div>
);
}

Preview Mode + useQuerySubscription

Another common scenario is being able to activate real-time updates of draft content only for content editors that are signed-in to the website via Preview Mode:

In this case, you don't want to expose your API token or pass down additional arguments to regular users, so:

  • Make sure to pass the includeDrafts: true option only if Preview Mode is active (that is, if context.preview is true), so that only content editors will see draft content;

  • If Preview Mode is off, fill in the subscription prop with just initialData and enabled: false options, without any additional clutter.

Here's an example snippet:

import { load } from '~/lib/datocms';
const BLOG_POST_QUERY = `
query HomePage {
blogPost {
title
}
}
`;
export async function loader({ request }) {
const session = await getSession(request.headers.get('Cookie'));
const previewModeActive = session.has('preview');
const initialData = await load(BLOG_POST_QUERY, {
includeDrafts: previewModeActive,
});
return {
subscription: previewModeActive
? {
query: BLOG_POST_QUERY,
initialData,
token: process.env.DATOCMS_READONLY_TOKEN,
environment: process.env.DATOCMS_ENVIRONMENT,
includeDrafts: true,
}
: {
enabled: false,
initialData,
};
};
}

If you want to directly see the final result, we've prepared a fully working Next.js blog, with real-time updates of draft content in Preview Mode:

Remix Blog
Remix Blog
Publish this demo online with just three clicks in a matter of minutes.
Deploy the demo project