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';
    export async function loader() {
    const graphqlRequest = {
    query: `query HomePage($limit: IntType) {
    allBlogPosts(first: $limit) {
    title
    }
    }`,
    variables: { limit: 10 },
    };
    return {
    subscription: {
    ...graphqlRequest,
    initialData: await load(graphqlRequest),
    token: process.env.DATOCMS_READONLY_TOKEN,
    },
    };
    }
    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';
    export async function loader({ request }) {
    const session = await getSession(request.headers.get('Cookie'));
    const previewModeActive = session.has('preview');
    const graphqlRequest = {
    query: `query HomePage($limit: IntType) {
    allBlogPosts(first: $limit) {
    title
    }
    }`,
    variables: { limit: 10 },
    includeDrafts: previewModeActive,
    };
    const initialData = await load(graphqlRequest);
    return {
    subscription: previewModeActive
    ? {
    ...graphqlRequest,
    initialData,
    token: process.env.DATOCMS_READONLY_TOKEN,
    }
    : {
    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
    Try the full-fledged DatoCMS demo project in minutes.
    Deploy the demo project