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.
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>);}
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: