问题描述
我正在遵循本指南:https://relay.dev/docs/en/quick-start-guide#composing-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
}
}
`,})
(以上片段需要根据编译器要求正确命名)
然后要做的是不将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
}
}
`
那也不行吗?