Displaying Content in React
Fetch Dyrected content in a React SPA, render common field types correctly, and prove one real route before moving into preview.
Use this page when your Cloud content model exists and you want your React routes to render real Dyrected content instead of hardcoded placeholders.
By the end, you should know the recommended client setup for a React app, how to fetch a document, and how to render the common Dyrected field shapes before you add preview.
This page comes after the content model and first content exist. Once one real route renders correctly, the next step is to open that same route in Dyrected's preview flow.
The mental model
In a React SPA, Dyrected does not render the page for you. Your route still owns the component tree. Dyrected's job is to supply the data shape, while your app decides how that data becomes UI.
That means displaying content is a two-part job:
- make the Dyrected client available in the app
- fetch the document you need and render its fields correctly
Most fields are plain values. The special cases are usually:
- uploads and images
- rich text
- blocks
Start by wiring the client once
DyrectedProvider makes one configured client available to the rest of the React tree.
Wrap your app root once:
import ReactDOM from "react-dom/client";
import { DyrectedProvider } from "@dyrected/react";
import { createClient } from "@dyrected/sdk";
import App from "./App";
const client = createClient({
baseUrl: import.meta.env.VITE_DYRECTED_URL,
apiKey: import.meta.env.VITE_DYRECTED_API_KEY,
siteId: import.meta.env.VITE_DYRECTED_SITE_ID,
});
ReactDOM.createRoot(document.getElementById("root")!).render(
<DyrectedProvider client={client}>
<App />
</DyrectedProvider>,
);This gives your routes one shared Cloud client instead of rebuilding it ad hoc in every page.
A simple page route example
This example fetches one document from the pages collection and renders it in a client-side route:
import { useEffect, useState } from "react";
import { DyrectedImage, DyrectedRichText, useDyrected } from "@dyrected/react";
export function CmsPage({ slug }: { slug: string }) {
const { client } = useDyrected();
const [page, setPage] = useState<any | null>(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
let cancelled = false;
client
.collection("pages")
.find({
where: { slug: { equals: slug } },
depth: 1,
limit: 1,
})
.exec()
.then((result) => {
if (cancelled) return;
setPage(result.docs[0] ?? null);
setLoading(false);
});
return () => {
cancelled = true;
};
}, [client, slug]);
if (loading) return <p>Loading...</p>;
if (!page) return <p>Page not found.</p>;
return (
<article className="prose mx-auto">
<h1>{page.title}</h1>
{page.featuredImage ? <DyrectedImage media={page.featuredImage} alt={page.title} /> : null}
{page.content ? <DyrectedRichText content={page.content} /> : null}
</article>
);
}The important pattern is not the styling. It is the separation:
- the route fetches typed content from Dyrected
- the component decides how that content should look in the real app
Which renderer to use for common field shapes
The React integration gives you the helpers you will need most often:
DyrectedImagefor image uploadsDyrectedMediafor mixed mediaDyrectedRichTextfor HTML produced by the editorBlocksfor block-based page sections
Use plain JSX for ordinary text, dates, booleans, and simple relationships. Reach for the helpers when the field shape already carries rendering semantics.
Rendering blocks
If your collection uses a blocks field, map each blockType to a real component:
import { Blocks } from "@dyrected/react";
import { HeroBlock } from "./blocks/HeroBlock";
import { CtaBlock } from "./blocks/CtaBlock";
<Blocks
items={page.layout}
path="layout"
components={{
hero: HeroBlock,
cta: CtaBlock,
}}
/>;This matters for two reasons:
- it keeps the layout system in your codebase
- it gives live preview a stable way to map block content back to the right field paths later
Recommended path
For a first render path, do not try to make every content type dynamic at once.
Start by proving one page end to end:
- provide the client once
- fetch one collection
- render one route
- confirm an edit in the admin changes the frontend output
Once that works, expand to shared navigation, more collections, and eventually block-based layouts if the app needs them.
Escape hatches
If JavaScript is not the consumer, drop down to the REST API Overview. For React SPAs, the SDK and @dyrected/react helpers should stay the default path.
For broader component coverage beyond the quick-start use case, continue to Displaying Content Overview and SDK API Overview.
Success check
You are ready for the next step when:
- a real React route renders content fetched from Dyrected Cloud
- the route handles missing content safely
- at least one structured field shape is rendered with the proper helper
Once that is true, continue to Adding a Visual Editor in React.
Creating Your First Content
Create the first page and shared records in Dyrected Cloud so your React app can render real content instead of wiring against an empty CMS.
Adding a Visual Editor in React
Add live preview and click-to-edit to a React route that already renders Dyrected content, starting with the simplest supported preview flow.