Remix Blog
Words are nice... but code speaks louder. Dive into a fully commented project template, showcasing these techniques (and more) in action.
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';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>);}
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: