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

问题描述 投票:0回答:2

我正在遵循本指南: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 应该期望一个值列表而不是单个值?

我完全陷入困境。

reactjs relay relaymodern
2个回答
1
投票

我想我遇到了这个问题,并且我想我按照您的建议解决了它,通过在查询中包含需要别名的字段:

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
      }
  }
`

这也应该行得通吗?


0
投票

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
   }
  }

希望这对刚接触接力的人有帮助。

© www.soinside.com 2019 - 2024. All rights reserved.