@contentful/experiences-react

中文文档
0.15.9发布于 2026/11/07MITTypeScriptES Module近 30 天下载 4817

React adapter for Contentful Experiences — Server and Client renderers over a PortableRenderPlan

原始使用文档
文档目录13 节
  1. Public API
  2. Authoring
  3. Fetching
  4. Resolver
  5. Live preview
  6. Renderers
  7. Custom renderer ( @contentful/experiences-react/custom-rend…
  8. Styling + runtime context (hooks)
  9. Re-exported types and utilities
  10. Quick reference
  11. Slot children
  12. License
  13. Runtime Experience parameters

@contentful/experiences-react

⚠️ Alpha. Published to npm. APIs are unstable and will change.

The React adapter for the Contentful Experiences SDK. You bring your own React components; it renders Experience payloads from the Experience Delivery API (XDA) with them.

npm install @contentful/experiences-react

This is the only rendering SDK package you install. It re-exports everything you need from @contentful/experiences-sdk-core, @contentful/experiences-design, and @contentful/experiences-client. The optional @contentful/experiences-live-preview package is also customer-facing and provides the framework-neutral live-preview client.


Public API

Authoring

defineComponent<Props>(config); // Type-narrowing identity for component-type configs
defineExperienceTemplate<Props>(config); // Same shape, for coded Experience Template configs

Fetching

fetchExperience(experienceOptions, clientOptions, resolveOptions)  // Async; fetches by Destination path/node id or Experience id and resolves in one call
fetchDestinationSitemap(destinationOptions, clientOptions, paginationOptions?) // Async; lists every routable path in a Destination
fetchPreviewSession(previewSessionOptions, clientOptions, resolveOptions) // Async; fetches and resolves a Preview Session Experience
createClient(options)                       // Functional constructor matching the SDK's option shape
ContentfulViewDeliveryClient                // Re-exported delivery client for advanced use cases
NotFoundError                               // Thrown when the Experience ID or Destination path doesn't exist
DestinationPreviewNotSupportedError         // Thrown when preview is requested for a Destination fetch
PreviewSessionFetchError                   // Thrown when fetching a Preview Session fails
LivePreviewConnectionError                 // Reported when the live-preview connection fails
ContentfulViewDelivery                      // Full error namespace from the delivery client
type ExperienceOptions, ByIdExperienceOptions, ByDestinationPathExperienceOptions,
  ByDestinationNodeIdExperienceOptions, DestinationRedirectResult, DestinationSitemapResult,
  FetchDestinationSitemapOptions, FetchDestinationSitemapPaginationOptions, SitemapPathItem,
  PreviewSessionExperienceOptions, PreviewSessionClientOptions,
  PreviewSessionResolveOptions, ClientOptions, ResolveOptions, CreateClientOptions

Serve pages from a Destination: the URL path is the Destination path. A redirect node comes back as a value, not an error. Preview is not supported on Destinations (it throws DestinationPreviewNotSupportedError); use the by-id form for preview.

const result = await fetchExperience(
  { spaceId, destinationId, path: '/demo/landing' },
  { accessToken },
  { config: experienceConfig }
);
if ('redirect' in result) {
  // follow it: navigate to result.redirect.path
}
// otherwise `result` is a PortableRenderPlan

// Enumerate every routable path, for example to prerender
const sitemap = await fetchDestinationSitemap({ spaceId, destinationId }, { accessToken });
const paths = sitemap.items.map((item) => item.path); // follow sitemap.pages.next for more

Use fetchPreviewSession for the initial render when the Contentful app provides a preview_session_id. It fetches the current Preview Session snapshot and resolves it into a PortableRenderPlan. Use useLivePreview to receive subsequent WebSocket updates:

const plan = await fetchPreviewSession(
  { spaceId, environmentId, sessionId },
  { previewToken },
  { config: experienceConfig }
);

If the Preview Session references resources from other spaces, pass the same encoded resourceResolution value in the previewSessionOptions passed to fetchPreviewSession and useLivePreview.

Resolver

resolveExperience(payload, config, opts?)   // Async; walks payload, runs resolveData, returns a PortableRenderPlan

Live preview

Use useLivePreview when the app should subscribe to Preview Session updates, resolve each payload, and render the resulting plan from data:

const livePreview = useLivePreview({
  previewSessionOptions,
  initialPayload,
  initialPlan,
  resolveOptions: { config: experienceConfig },
});

<ClientExperienceRenderer experience={livePreview.data} config={experienceConfig} />;

For separate access to the raw payload and rendered plan, use useLivePreviewExperience and useExperiencePlan:

const livePreview = useLivePreviewExperience({
  previewSessionOptions: {
    spaceId,
    environmentId,
    previewToken,
    sessionId,
  },
  initialPayload,
});

const plan = useExperiencePlan({
  payload: livePreview.data,
  initialPlan,
  resolveOptions: { config: experienceConfig },
});

<ClientExperienceRenderer experience={plan.data} config={experienceConfig} />;

useLivePreviewExperience returns the latest raw Experience payload. initialPayload seeds the first value. useExperiencePlan turns that payload into the PortableRenderPlan consumed by the renderer and keeps the current rendered experience while an update is being resolved.

The live-preview results also expose error when the Preview Session connection fails. The last valid data remains available.

Renderers

ServerExperienceRenderer; // RSC-friendly renderer
ClientExperienceRenderer; // Client renderer, alias: ExperienceRenderer
MissingComponent; // Default fallback for unregistered component types

Custom renderer (@contentful/experiences-react/custom-renderer)

For hosts that render a plan themselves instead of using ServerExperienceRenderer. resolveNodeProps returns each node's component and merged props, ExperienceNode renders it the way the SDK renderers do, and createExperienceNode renders a node's serializable snapshot where components can't be passed as props. ServerExperienceRenderer and ClientExperienceRenderer render every node through the same resolveNodeProps + ExperienceNode.

resolveNodeProps(node, config); // ResolvedNode: 'resolved' (component, props, design, contentful, snapshot) | 'unregistered'
ExperienceNode; // Renders one resolved node or snapshot exactly as the SDK renderers do
createExperienceNode(components, experienceTemplates?); // ExperienceNode with its registry bound, for snapshots
type ResolvedNode, NodeSnapshot, ExperienceNodeProps;

Styling + runtime context (hooks)

useDesignValues<T>(); // Escape hatch: the same resolved design record that auto-fills props
toCss(design, options?); // Turns a design record into CSSProperties, keeping only real CSS keys
useExperience(); // RenderContext: debug, metadata
useContentfulComponent(); // Raw payload for the enclosing node (or null), including `attribution`
useContentfulExperienceTemplate(); // Same, for an enclosing coded Experience Template node
getTrackingAttributes(attribution); // Props to spread on a node's outermost element for interaction tracking
type ToCssOptions;

Resolved design values are auto-filled onto your component's props by key, alongside content. Styling from those props is the one recommended path. useDesignValues() exposes the same record as an escape hatch. Reach for it only for a nested child that isn't itself a registered component, or for design needed outside the render path (an effect, an imperative measurement) — see Styling components. Token resolution is configured with resolveToken on your Config (type ResolveToken).

Re-exported types and utilities

// From core
type Config, Components, ExperienceTemplates, Registration, ExperienceTemplateRegistration,
type ComponentConfig, ExperienceTemplateConfig,
type ContentfulComponent, ContentfulExperienceTemplate,
type RenderContext, ResolveToken,
type ExperiencePayload, ExperienceNode, ComponentNode, ExperienceTemplateNode,
type PortableRenderPlan, PortableRenderNode, PortableRegistration,
type DesignPropValue, ManualDesignValue, DesignToken, ExperienceContext, ResolveContext,
type ResolverConfig, ResolveExperienceOptions

// From design
isCssProperty, toCssKey, CSS_PROPERTIES

Quick reference

// components/Button.tsx: content + resolved design both arrive as props
'use client';

interface ButtonProps {
  label?: string;
  url?: string;
  backgroundColor?: string; // resolved design, auto-filled
  color?: string;
}

export function Button({ label, url, backgroundColor, color }: ButtonProps) {
  return (
    <a href={url} style={{ background: backgroundColor, color }}>
      {label}
    </a>
  );
}
// lib/experience-config.tsx
import {
  defineComponent,
  type Components,
  type Config,
  type ResolveToken,
} from '@contentful/experiences-react';

import { Button } from './components/Button';

const components: Components = {
  // Bare component, or defineComponent({...}) when you need defaults/resolveData.
  Button: defineComponent({
    resolveData: ({ content }) => ({ url: ensureScheme(content.url) }),
    component: Button,
  }),
};

const resolveToken: ResolveToken = (token) => designTokens[token.value];

export const experienceConfig: Config = { components, resolveToken };
// app/experiences/[id]/page.tsx: in a server component, fetching by Experience id
import { fetchExperience, ServerExperienceRenderer } from '@contentful/experiences-react';

const experience = await fetchExperience(
  { spaceId: process.env.SPACE_ID!, environmentId: 'master', experienceId: id },
  { accessToken: process.env.CDA_TOKEN! },
  { config: experienceConfig }
);
return <ServerExperienceRenderer experience={experience} config={experienceConfig} />;

Slot children

Every slot arrives as a prop named after the slot, holding an array of pre-rendered nodes (ReactNode[]) keyed by the renderer — not a single wrapping node. Drop the array straight into JSX for the common "just render them" case (React renders keyed arrays), or map / filter over it to wrap, reorder, or drop children individually.

// components/Section.tsx
import type { ReactNode } from 'react';

export function Section({ children }: { children?: ReactNode[] }) {
  // Common case — render them all:
  return <div>{children}</div>;

  // Or take control of each child:
  // return (
  //   <div>
  //     {children?.map((child, i) => (
  //       <div className="cell" key={i}>{child}</div>
  //     ))}
  //   </div>
  // );
}

children is not special — it is simply the conventional name for the default slot. Every slot is merged into props under its own name, each as its own ReactNode[], so a component with a header slot just declares header?: ReactNode[] and renders it the same way. This applies identically to coded Experience Templates: a template with a content slot receives a content prop.

For the full getting-started walkthrough, merge-precedence rules, and design rationale, see the root README and AGENTS.md.


License

MIT. See the repository LICENSE and NOTICE for full attribution.

Runtime Experience parameters

By-ID fetchExperience accepts parameters, for example { featuredPosts: { limit: 6, order: '-fields.title' } }. Scalars are strings or numbers; Record leaves have one level. Order is one signed fields.<apiName> or sys.<id> path. Refetch with changed values, then replace the renderer's plan. Exports include ExperienceParameters, ExperienceParameterValue, ExperienceParameterRecord, and ExperienceParameterOrder. See the collection/refetch example.

版本与发布记录

@contentful/experiences-react 共发布 69 个版本,首次发布于 2026/07/21;过去 12 个月发布了 69 个版本。

版本发布日期距今
0.15.9latest2026/11/074 天前
0.15.82026/11/055 天前
0.15.72026/11/055 天前
0.15.62026/11/056 天前
0.15.52026/11/046 天前
0.15.42026/10/3111 天前

关于 @contentful/experiences-react 的常见问题

@contentful/experiences-react 是什么?

React adapter for Contentful Experiences — Server and Client renderers over a PortableRenderPlan

如何安装 @contentful/experiences-react?

在项目目录运行 npm install @contentful/experiences-react,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:react(^18.0.0 || ^19.0.0)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@contentful/experiences-react 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@contentful/experiences-react 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@contentful/experiences-react 可以商用吗?

@contentful/experiences-react 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@contentful/experiences-react 的下载量有多少?

根据 npm 官方下载统计,@contentful/experiences-react 在 2026/10/11 – 2026/11/09 这 30 天内被下载 4,817 次,日均约 161 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@contentful/experiences-react 还在维护吗?

最新版本 0.15.9 发布于 2026/11/07(4 天前);至今共发布 69 个版本,其中过去 12 个月发布了 69 个;首次发布于 2026/07/21。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。