我正在遵循本指南:https://relay.dev/docs/en/quick-start-guide#composition-fragments
我正在尝试创建一个更高级别的片段容器来从 RootQuery 查询数据:
export const FormInstanceListContainer: FunctionComponent<Props> = props => {
const { data, ...rest } = props
const { formInstances } = data
return (
<FormInstanceList
formInstances={formInstances}
{...rest} // Forward all the other props
/>
)
}
export default createFragmentContainer(FormInstanceListContainer, {
data: graphql`
fragment FormInstanceListContainer_data on RootQuery
@argumentDefinitions(status: { type: "FormStatus" }) {
formInstances(status: $status) {
id
form {
id
name
}
status
createdAt
submittedAt
}
}
`,
})
只要我只需要呈现这些列表之一,这种方法就很有效。这是一个使用示例:
const IndexPage: NextPage<QueryResponse> = data => {
const handleOpenClick = (formInstance: FormInstance) => {
NextRouter.push(`/form-instance/${formInstance.uuid}`)
}
const handleEditClick = (formInstance: FormInstance) => {
NextRouter.push(`/form-instance/${formInstance.uuid}/edit`)
}
return (
<DefaultLayout>
<Container maxWidth="md">
<Typography variant="h5" style={{ marginBottom: 25 }}>
My drafts
</Typography>
<FormInstanceListContainer
data={data}
onOpenClick={handleOpenClick}
onEditClick={handleEditClick}
/>
</Container>
</DefaultLayout>
)
}
export default withData<pages_dashboard_Query>(IndexPage, {
query: graphql`
query pages_dashboard_Query {
...FormInstanceListContainer_data @arguments(status: DRAFT)
}
`,
})
不幸的是,我需要并排呈现其中 2 个列表...一个用于草稿表格,另一个用于已提交的表格。
我不能只包含再次展开相同的片段:
query pages_dashboard_Query {
...FormInstanceListContainer_data @arguments(status: DRAFT)
...FormInstanceListContainer_data @arguments(status: SUBMITTED)
}
错误: 预期名称或别名为“formInstances”的同一父级上的所有字段都具有相同的名称和参数。
那么我如何才能在同一页面上拥有多个具有不同数据的
FormInstanceListContainer
?我设计片段容器的方式是否陷入了死胡同?
如果我能够在顶级页面中运行查询(从那时起我可以使用别名)并将结果列表传递给
FormInstanceListContainer
,问题就会得到解决。要做到这一点,在我看来,FormInstanceListContainer
必须请求查询的字段而不是查询本身:
export default createFragmentContainer(FormInstanceListContainer, {
formInstance: graphql`
fragment FormInstanceListContainer_formInstance on FormInstance {
id
form {
id
name
}
status
createdAt
submittedAt
}
`,
})
但是,现在 Relay 假设应将 FormInstance
的
单个实例传递到容器,而不是它们的列表。我尝试传递列表的任何方式都会导致 Relay 崩溃。是否可以指示 Relay 应该期望一个值列表而不是单个值?
我完全陷入困境。
我想我遇到了这个问题,并且我想我按照您的建议解决了它,通过在查询中包含需要别名的字段:
graphql`
fragment FormInstanceFields on FormInstance {
id
form {
id
name
}
status
createdAt
submittedAt
}
`
export default withData<pages_dashboard_Query>(IndexPage, {
query: graphql`
query pages_dashboard_Query {
drafts: formInstances(status: DRAFT) {
...FormInstanceFields
}
submitted: formInstances(status: SUBMITTED) {
...FormInstanceFields
}
}
`,
})
(以上片段需要根据编译器要求正确命名)
那么要做的就是not将
FormInstanceList
包装在片段容器中,因为正如您所指出的,这会导致错误。包装它的冲动很强烈,因为使用基于 HOC 的 API,本能是一路向下包装整个渲染树。但在这种情况下这不起作用。
相反,将每个
FormInstance
包装在片段容器中(我猜你已经在这样做了)。然后它就会起作用。 drafts
和 submitted
字段将包含中继存储引用数组,您可以对它们进行交互并将每个数组传递给 FormInstanceContainer
。
这可能感觉不对,但如果你从即将推出的 hooks API 或 relay-hooks 的角度来考虑,那就没什么问题了。
编辑
有一段时间没有使用 Relay,但我认为您甚至可以通过执行以下操作来将容器保留在各个级别:
graphql`
fragment FormInstanceListContainer_data on RootQuery {
drafts: formInstances(status: DRAFT) {
...FormInstanceFields
}
submitted: formInstances(status: SUBMITTED) {
...FormInstanceFields
}
}
`
这也应该行得通吗?
Relay 不允许在单个查询中分散多个片段,前提是这些片段以不同的
where clause
条件从同一个表中获取数据。
您需要做的就是创建单个片段,而不是像下面那样创建多个片段。
// Your Query...
graphql`
query MyQuery($currentTs: bigint!) {
...MyFragment @arguments(currentTs: $currentTs)
}
// Your Fragment...
fragment MyFragment on query_root @argumentDefinitions(
currentTs: {type: "bigint"},
) {
one: appointments_connection(where: { package_type_id: { _eq: 4 }, real_status: { _in: [1, 8] }, ends_at: { _gt: $currentTs } }, first: 1, order_by: { starts_at: asc }) {
id
title
}
two: appointments_connection(where: {package_type_id: {_eq: 1}}, first: 1) {
id_random
}
three: appointments_connection(where: {real_status: {_in: [1, 8]}, ends_at: {_gt: $currentTs}}, first: 3, order_by: {starts_at: asc}) {
title
starts_at
}
}
希望这对刚接触接力的人有帮助。