useCms()
Reads the CmsAdapter from React context. Returns the adapter (or
null when the provider was given null).
import { useCms } from 'propeller-v2-cms-react';
const cms = useCms();
// ^^ CmsAdapter | null
When to use
Client islands that need optional access to the adapter — e.g. preview banners, draft-mode toggles, "edit in CMS" links. Anything fetched on the server should call the adapter directly, not through this hook (a server component can't use context).
Outside the provider
If a component calling useCms() is not inside a <CmsAdapterProvider>,
the hook returns null. It does not throw — the contract is "this
shop may not have a CMS configured", and that's a valid state.
Patterns
Hide UI when no CMS is wired
function PreviewBanner() {
const cms = useCms();
if (!cms) return null;
return <div>Preview mode active</div>;
}
Fetch on the client when the page slug is dynamic
function CmsSnippet({ slug }: { slug: string }) {
const cms = useCms();
const [page, setPage] = useState<CmsPage | null>(null);
useEffect(() => {
if (!cms) return;
cms.getPage(slug).then(setPage).catch(() => setPage(null));
}, [cms, slug]);
if (!page) return null;
return <CmsPageRenderer page={page} renderers={cmsRenderers} />;
}
In Next.js App Router shops, prefer fetching on the server route and passing the page in as a prop. Client fetches add a waterfall and skip the framework's built-in caching.