canvas-data-fetching
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseData fetching
数据获取
Data fetching with SWR
使用SWR进行数据获取
Use SWR for all data fetching. It provides caching,
revalidation, and a clean hook-based API.
jsx
import useSWR from 'swr';
const fetcher = (url) => fetch(url).then((res) => res.json());
export default function Profile() {
const { data, error, isLoading } = useSWR(
'https://my-site.com/api/user',
fetcher,
);
if (error) return <div>Failed to load</div>;
if (isLoading) return <div>Loading...</div>;
return <div>Hello, {data.name}!</div>;
}所有数据获取操作均使用SWR完成。它提供缓存、重新验证功能,以及简洁的基于Hook的API。
jsx
import useSWR from 'swr';
const fetcher = (url) => fetch(url).then((res) => res.json());
export default function Profile() {
const { data, error, isLoading } = useSWR(
'https://my-site.com/api/user',
fetcher,
);
if (error) return <div>Failed to load</div>;
if (isLoading) return <div>Loading...</div>;
return <div>Hello, {data.name}!</div>;
}Fetching Drupal content with JSON:API
使用JSON:API获取Drupal内容
To fetch content from Drupal (e.g., articles, events, or other content types),
use the autoconfigured from the package combined
with for query building.
JsonApiClientdrupal-canvasDrupalJsonApiParamsImportant: Do not fabricate JSON:API resource payloads in Workbench mocks.
Components that fetch data should render their real loading, empty, or error
states in Workbench unless the user explicitly asks for a static, non-fetching
preview shape.
jsx
import { getNodePath, JsonApiClient } from 'drupal-canvas';
import { DrupalJsonApiParams } from 'drupal-jsonapi-params';
import useSWR from 'swr';
const Articles = () => {
const client = new JsonApiClient();
const { data, error, isLoading } = useSWR(
[
'node--article',
{
queryString: new DrupalJsonApiParams()
.addSort('created', 'DESC')
.getQueryString(),
},
],
([type, options]) => client.getCollection(type, options),
);
if (error) return 'An error has occurred.';
if (isLoading) return 'Loading...';
return (
<ul>
{data.map((article) => (
<li key={article.id}>
<a href={getNodePath(article)}>{article.title}</a>
</li>
))}
</ul>
);
};
export default Articles;要从Drupal中获取内容(例如文章、活动或其他内容类型),请结合使用包中自动配置的和用于构建查询的。
drupal-canvasJsonApiClientDrupalJsonApiParams重要提示: 不要在Workbench模拟中伪造JSON:API资源负载。除非用户明确要求静态、非获取数据的预览形态,否则获取数据的组件应在Workbench中渲染其真实的加载、空数据或错误状态。
jsx
import { getNodePath, JsonApiClient } from 'drupal-canvas';
import { DrupalJsonApiParams } from 'drupal-jsonapi-params';
import useSWR from 'swr';
const Articles = () => {
const client = new JsonApiClient();
const { data, error, isLoading } = useSWR(
[
'node--article',
{
queryString: new DrupalJsonApiParams()
.addSort('created', 'DESC')
.getQueryString(),
},
],
([type, options]) => client.getCollection(type, options),
);
if (error) return 'An error has occurred.';
if (isLoading) return 'Loading...';
return (
<ul>
{data.map((article) => (
<li key={article.id}>
<a href={getNodePath(article)}>{article.title}</a>
</li>
))}
</ul>
);
};
export default Articles;Including relationships with addInclude
addInclude使用addInclude
包含关联关系
addIncludeWhen you need related entities (e.g., images, taxonomy terms), use
to fetch them in a single request.
addIncludeAvoid circular references in JSON:API responses. SWR uses deep equality
checks to compare cached data, which fails with "too much recursion" errors when
the response contains circular references.
Do not include self-referential fields. Fields that reference the same
entity type being queried (e.g., on an article query)
create circular references: Article A references Article B, which references
back to Article A. If you need related content of the same type, fetch it in a
separate query.
field_related_articlesUse to limit the response. Always specify only the fields you
need. This improves performance and helps avoid circular reference issues:
addFieldsjsx
const params = new DrupalJsonApiParams();
params.addSort('created', 'DESC');
params.addInclude(['field_category', 'field_image']);
// Limit fields for each entity type
params.addFields('node--article', [
'title',
'created',
'field_category',
'field_image',
]);
params.addFields('taxonomy_term--categories', ['name']);
params.addFields('file--file', ['uri', 'url']);当你需要获取关联实体(例如图片、分类术语)时,请使用在单次请求中获取它们。
addInclude避免JSON:API响应中出现循环引用。 SWR使用深度相等检查来比较缓存数据,当响应包含循环引用时会触发“递归过深”错误。
不要包含自引用字段。 引用正在查询的同一实体类型的字段(例如文章查询中的)会创建循环引用:文章A引用文章B,而文章B又引用回文章A。如果你需要同一类型的关联内容,请通过单独的查询获取。
field_related_articles使用限制响应内容。 始终只指定你需要的字段。这可以提升性能,并有助于避免循环引用问题:
addFieldsjsx
const params = new DrupalJsonApiParams();
params.addSort('created', 'DESC');
params.addInclude(['field_category', 'field_image']);
// Limit fields for each entity type
params.addFields('node--article', [
'title',
'created',
'field_category',
'field_image',
]);
params.addFields('taxonomy_term--categories', ['name']);
params.addFields('file--file', ['uri', 'url']);Creating content list components
创建内容列表组件
When building a component that displays a list of content items (e.g., a news
listing, event calendar, or resource library), follow this workflow:
在构建显示内容项列表的组件(例如新闻列表、活动日历或资源库)时,请遵循以下流程:
Setup gate
前置配置检查
Before any JSON:API discovery or content-type checks, verify local setup:
- Check that a file exists in the project root.
.env - If exists, verify
.envis set. ReadCANVAS_SITE_URLif present; otherwise, useCANVAS_JSONAPI_PREFIX.jsonapi - Send an HTTP request to . Success means HTTP
{CANVAS_SITE_URL}/{CANVAS_JSONAPI_PREFIX}.200 - If the request is successful, continue with Drupal data fetching.
- If the request is unsuccessful (or required values are missing), ask the user whether they want to:
.env- Configure Drupal connectivity now, or
- Continue with static content instead of Drupal fetching.
- If the user chooses to configure connectivity, provide instructions:
.envCANVAS_SITE_URL=<their Drupal site URL>- (optional; defaults to
CANVAS_JSONAPI_PREFIX=jsonapi) Then wait for the user to confirm they updatedjsonapi, and test the request again..env
- If the user chooses not to configure connectivity, proceed with static content.
- Do not update Vite config () to troubleshoot connectivity. Connectivity issues must be resolved via correct
vite.config.*values and Drupal site availability, not build tooling changes..env
在进行任何JSON:API发现或内容类型检查之前,请先验证本地环境配置:
- 检查项目根目录下是否存在文件。
.env - 如果文件存在,验证是否已设置
.env。如果存在CANVAS_SITE_URL则读取该值;否则使用默认值CANVAS_JSONAPI_PREFIX。jsonapi - 向发送HTTP请求。请求成功的标志是返回HTTP
{CANVAS_SITE_URL}/{CANVAS_JSONAPI_PREFIX}状态码。200 - 如果请求成功,继续进行Drupal数据获取操作。
- 如果请求失败(或缺少必要的配置值),询问用户是否希望:
.env- 立即配置Drupal连接,或者
- 继续使用静态内容而非从Drupal获取数据。
- 如果用户选择配置连接,请提供配置说明:
.envCANVAS_SITE_URL=<你的Drupal站点URL>- (可选;默认值为
CANVAS_JSONAPI_PREFIX=jsonapi)。然后等待用户确认已更新jsonapi文件,并重试请求。.env
- 如果用户选择不配置连接,则继续使用静态内容。
- 不要修改Vite配置文件()来排查连接问题。连接问题必须通过正确的
vite.config.*配置值和Drupal站点的可用性来解决,而非修改构建工具配置。.env
Step 1: Analyze the list structure
步骤1:分析列表结构
Examine the design to understand what data each list item needs:
- What fields are displayed (title, date, image, category, etc.)?
- How are items sorted (newest first, alphabetical, etc.)?
- Are there filters or pagination?
查看设计稿,了解每个列表项需要哪些数据:
- 需要显示哪些字段(标题、日期、图片、分类等)?
- 项的排序方式(最新优先、字母顺序等)?
- 是否包含过滤器或分页功能?
Step 2: Identify or request the content type
步骤2:识别或请求创建内容类型
Before writing code, verify that an appropriate content type exists in Drupal:
-
Check the JSON:API endpoint of your local Drupal site (configured viaand
CANVAS_SITE_URLenvironment variables) to find a content type that matches the required structure. Use a plainCANVAS_JSONAPI_PREFIXrequest for this check, after passing the Setup gate.fetch -
If a matching content type exists, use it and note which fields are available.
-
If no matching content type exists, stop and prompt the user to create one. Provide:
- A suggested content type name
- The required field structure based on the list design
在编写代码之前,请验证Drupal中是否存在合适的内容类型:
-
通过和
CANVAS_SITE_URL环境变量配置的本地Drupal站点的JSON:API端点,查找与所需结构匹配的内容类型。通过前置配置检查后,使用普通的CANVAS_JSONAPI_PREFIX请求完成此检查。fetch -
如果存在匹配的内容类型,请使用它并记录可用的字段。
-
如果不存在匹配的内容类型,请停止操作并提示用户创建一个。提供:
- 建议的内容类型名称
- 基于列表设计所需的字段结构
Step 3: Build the component
步骤3:构建组件
Create the content list component using JSON:API to fetch content. Only use
fields that actually exist on the content type—do not assume fields exist
without verifying.
使用JSON:API获取内容,创建内容列表组件。仅使用内容类型上实际存在的字段——不要在未验证的情况下假设字段存在。
Handling filters
处理过滤器
If the list includes filters based on entity reference fields (e.g., filter by
category, filter by author):
- Do not hardcode filter options. Filter options should be fetched dynamically using JSON:API.
- Fetch the available options for each filter (e.g., all taxonomy terms in a vocabulary) and populate the filter UI from that data.
This ensures filters stay in sync with the actual content in Drupal and new
options appear automatically without code changes.
如果列表包含基于实体引用字段的过滤器(例如按分类筛选、按作者筛选):
- 不要硬编码过滤器选项。 过滤器选项应通过JSON:API动态获取。
- 获取每个过滤器的可用选项(例如词汇表中的所有分类术语),并据此填充过滤器UI。
这样可以确保过滤器与Drupal中的实际内容保持同步,新选项无需修改代码即可自动显示。