如何在同一个顶级片段容器中拥有多个同级实例?

问题描述

我正在遵循本指南: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包裹在一个片段容器中(我想您已经在这样做了)。然后它将起作用。 draftssubmitted字段将包含中继存储引用的数组,您可以对其进行交互,然后将每个传递给FormInstanceContainer

这可能是错的,但是如果您从即将到来的hooks API或relay-hooks的角度考虑它,那真的没有什么错。


编辑

已经有一段时间没有使用Relay了,但我认为您甚至可以通过执行以下操作将容器保持在各个级别:

graphql`
  fragment FormInstanceListContainer_data on RootQuery {
      drafts: formInstances(status: DRAFT) {
        ...FormInstanceFields
      }
      submitted: formInstances(status: SUBMITTED) {
        ...FormInstanceFields
      }
  }
`

那也不行吗?

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...