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 Next.js 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.

    Step-by-step tutorial

    We have prepared a step-by-step tutorial that shows how to get to live-previews of draft content, so be sure to check that out!

    How to use the useQuerySubscription hook

    The react-datocms package exposes a useQuerySubscription hook that makes it trivial to make any Next.js page updated in real-time. The hook works by streaming any changes to the GraphQL response to the browser.

    In the getStaticProps function — or getServerSideProps, depending on how fresh you want to be the results on the first full-page load — you can perform the GraphQL request just like in the previous examples.

    The result of the query performed server-side is then passed down to the component page as the initialData argument of the useQuerySubscription hook. The hook also requires other arguments, such as the query itself, and the token to use to stream the changes.

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

    import { useQuerySubscription } from "react-datocms";
    import { request } from '../lib/datocms';
    const HOMEPAGE_QUERY = `query HomePage($limit: IntType) {
    allBlogPosts(first: $limit) {
    title
    }
    }`;
    export async function getStaticProps() {
    const graphqlRequest = {
    query: HOMEPAGE_QUERY,
    variables: { limit: 10 },
    };
    return {
    props: {
    subscription: {
    ...graphqlRequest,
    initialData: await request(graphqlRequest),
    token: process.env.NEXT_PUBLIC_DATOCMS_API_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>
    );
    }

    If you want to directly see the final result, we've prepared a fully working Next.js demo, mimicking an Apple-like event coverage live blog:

    Next.js Event Coverage Liveblog
    Next.js Event Coverage Liveblog
    Try the full-fledged DatoCMS demo project in minutes.
    Deploy the demo project

    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 preview: true option only if Preview Mode is active (that is, if context.preview is true), so that only content editors will see draft content;
    • Use NEXT_ instead of NEXT_PUBLIC_ as the prefix for our env variable, so that the token will only be readable server-side;
    • 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:

    export async function getStaticProps(context) {
    const graphqlRequest = {
    query: HOMEPAGE_QUERY,
    variables: { limit: 10 },
    // If true, the Content Delivery API with draft content will be used
    preview: context.preview,
    };
    return {
    props: {
    subscription: context.preview
    ? {
    ...graphqlRequest,
    initialData: await request(graphqlRequest),
    token: process.env.NEXT_DATOCMS_API_TOKEN,
    }
    : {
    enabled: false,
    initialData: await request(graphqlRequest),
    },
    },
    };
    }

    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:

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