不推荐使用文档服务 API 更新可重复使用的组件
🌐 Updating repeatable components with the Document Service API is not recommended
Page summary:在 Strapi 5 中,文档的草稿和已发布版本使用不同的数字组件
id。通常,从已发布的响应中重用id来更新草稿会失败。建议在可用持久组件身份推出之前,要么替 换整个组件数组,要么在草稿 ID 上进行编辑。🌐 In Strapi 5, draft and published versions of a document use different numeric component
ids. Reusing anidfrom a published response to update the draft usually fails. Prefer replacing the full component array (or editing against draft ids) until a durable component identity ships.
在 Strapi 5 中,不推荐通过重复使用已发布 API 响应中的组件 id 来更新可重复组件,因为草稿与发布模式会影响 Document Service API 的交互。
🌐 In Strapi 5, it's not recommended to update repeatable components by reusing component ids from published API responses, because of how Draft & Publish interacts with the Document Service API.
此页面是重大更改数据库的一部分,提供关于重大更改的信息以及从 Strapi v4 迁移到 Strapi 5 的附加说明。
🌐 This page is part of the breaking changes database and provides information about the breaking change and additional instructions to migrate from Strapi v4 to Strapi 5.
重大 变更描述
🌐 Breaking change description
在 Strapi v4 中
你可以通过传递它的数字 id 来部分更新可重复的组件。
🌐 You could partially update a repeatable component by passing its numeric id.
在 Strapi 5 中
文档使用稳定的 documentId,但嵌套组件仍然使用状态本地数字 id。发布会创建新的组件行,因此同一模块的草稿和已发布版本有不同的 id。你不能把已发布的组件 id 当作文档级别的标识符。
🌐 Documents use a stable documentId, but nested components still use status-local numeric ids. Publishing creates new component rows, so the draft and published versions of the same block have different ids. You cannot treat a published component id like a document-level identifier.
迁移
🌐 Migration
本节重新组合了有关引入的重大更改的有用说明和程序。
🌐 This section regroups useful notes and procedures about the introduced breaking change.
注意
🌐 Notes
启用草稿和发布后,典型的内容 API 流程是这样的:
🌐 With Draft & Publish enabled, a typical Content API flow looks like this:
// Request: Content API returns the published version by default
GET /api/articles
// Response (published)
{
data: {
documentId: '…',
components: [
{ id: 2, name: 'component-1' },
{ id: 4, name: 'component-2' },
],
},
}
用那些已发布的 id 更新会生成草稿,它有不同的组件行 ID:
🌐 Updating with those published ids writes the draft, which has different component row ids:
PUT /api/articles/{documentId}
{
data: {
components: [
{ id: 2, name: 'component-1-updated' }, // published id, usually wrong for draft
],
},
}
这通常会因为 id: 2 没有链接到草稿条目而报错,比如 Some of the provided components in components are not related to the entity。这和 组件和动态区 域在 REST API 响应中不会返回 id 有关。
🌐 This often fails with an error such as Some of the provided components in components are not related to the entity, because id: 2 is not linked to the draft entry. This is related to the fact that components and dynamic zones do not return an id in REST API responses.
文档服务 在读取/更新时默认使用草稿,所以当你使用草稿组件 ID 时,id 可以在那儿(以及内容管理器里)进行原地更新。陷阱在于混合已发布的 ID 和草稿写入。
🌐 The Document Service defaults to the draft on read/update, so in-place updates by id can work there (and in the Content Manager) when you use draft component ids. The trap is mixing published ids with draft writes.
推荐的解决方法
🌐 Recommended workarounds
在有了持久的嵌套身份之前,使用以下其中一种。
🌐 Until a durable nested identity is available, use one of the following.
1. 替换整个组件数组(内容 API 推荐)
🌐 1. Replace the full component array (preferred for Content API)
省略组件 id 并发送完整的所需列表。Strapi 会在草稿上重新创建这些组件。这是对只看到已发布数据的 REST/GraphQL 客户端而言,支持且稳定的方法:
🌐 Omit component ids and send the complete desired list. Strapi recreates the components on the draft. This is the supported, non-fragile approach for REST/GraphQL clients that only see published data:
// Document Service
await strapi.documents('api::article.article').update({
documentId,
data: {
components: [
{ name: 'component-1-updated' },
{ name: 'component-2' },
],
},
});
// REST Content API
PUT /api/articles/{documentId}
{
"data": {
"components": [
{ "name": "component-1-updated" },
{ "name": "component-2" }
]
}
}
包括你想保留的每个组件。数组中遗漏的条目会从草稿中删除。
🌐 Include every component you want to keep. Entries omitted from the array are removed from the draft.
2. 针对草稿组件ID进行编辑(文档服务 / 管理风格)
🌐 2. Edit against draft component ids (Document Service / admin-style)
如果你能控制后端(自定义路由、脚本、文档服务),加载草稿,然后使用这些ID进行更新:
🌐 If you control the backend (custom routes, scripts, Document Service), load the draft, then update using those ids:
const draft = await strapi.documents('api::article.article').findOne({
documentId,
status: 'draft',
populate: ['components'],
});
await strapi.documents('api::article.article').update({
documentId,
data: {
components: draft.components.map((component) =>
component.id === targetDraftId
? { id: component.id, name: 'component-1-updated' }
: { id: component.id, name: component.name }
),
},
});
不要在这个模式中重用默认内容 API GET(已发布)的 ID。
🌐 Do not reuse ids from a default Content API GET (published) for this pattern.
3. 草稿和发布已禁用
🌐 3. Draft & Publish disabled
如果内容类型上禁用了草稿和发布,就只有一个组件行集,所以基于 ID 的更新问题不大。不过,为了让客户端代码更简单,还是建议使用整个数组替换的方式。
🌐 If Draft & Publish is disabled on the content-type, there is only one component row set, so id-based updates are less problematic. Prefer the full-array replace pattern anyway for simpler client code.