Next.js > 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 Draft Mode can see their work-in-progress 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).

    How to use the useQuerySubscription hook

    The react-datocms package exposes a useQuerySubscription hook that uses our Real-time Updates API to make any Next.js page update in real-time.

    We'll start with the following example, and modify it to activate real-time updates for any visitor of your website:

    const PAGE_CONTENT_QUERY = `{
    allBlogPosts { id title }
    site: _site {
    favicon: faviconMetaTags { attributes content tag }
    }
    }`;
    function getPageRequest() {
    return { query: PAGE_CONTENT_QUERY };
    }
    export async function generateMetadata() {
    const data = await performRequest(getPageRequest());
    return toNextMetadata(data.site.favicon);
    }
    export default async function HomePage() {
    const data = await performRequest(getPageRequest());
    return <LatestBlogPosts data={data} />
    }

    The first step is to build a <RealtimeLatestBlogPosts /> Client component, utilizing the useQuerySubscription hook:

    'use client';
    import { useQuerySubscription } from 'react-datocms';
    function RealtimeLatestBlogPosts({ subscription }) {
    const { data, error, status } = useQuerySubscription(subscription);
    return <LatestBlogPosts data={data} error={error} status={status} />;
    }

    Then, in our page component, we can replace the <LatestBlogPosts /> component with <RealtimeLatestBlogPosts />:

    export default async function HomePage() {
    const pageRequest = getPageRequest();
    const data = await performRequest(pageRequest);
    return (
    <RealtimeLatestBlogPosts
    subscription={{
    ...pageRequest,
    initialData: data,
    environment: process.env.NEXT_DATOCMS_ENVIRONMENT,
    token: process.env.NEXT_DATOCMS_API_TOKEN,
    }}
    />
    );
    }

    Draft Mode + useQuerySubscription

    Perhaps a more common scenario is being able to activate real-time updates not for every visitor, but only for content editors in Draft Mode, and showing also records in draft:

    In this case, the page component will change a bit, as we need to check draft mode activation and either render <RealtimeLatestBlogPosts /> or <LatestBlogPosts />:

    function getPageRequest({ includeDrafts }) {
    return { query: PAGE_CONTENT_QUERY, includeDrafts };
    }
    export default async function HomePage() {
    const { isEnabled } = draftMode();
    const pageRequest = getPageRequest({ includeDrafts: isEnabled });
    const data = await performRequest(pageRequest);
    if (isEnabled) {
    return (
    <RealtimeLatestBlogPosts
    subscription={{
    ...pageRequest,
    initialData: data,
    environment: process.env.NEXT_DATOCMS_ENVIRONMENT,
    token: process.env.NEXT_DATOCMS_API_TOKEN,
    }}
    />
    );
    }
    return <LatestBlogPosts data={data} />
    }

    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 Draft Mode:

    Next.js Blog
    Next.js Blog
    Try the full-fledged DatoCMS demo project in minutes.
    Deploy the demo project