大型react-apollo应用程序中片段组合的组织结构

问题描述 投票:5回答:1

我正在使用Apollo Client和React,我正在寻找一种策略来保持我的组件和组件数据要求的共存,以便父/兄弟/子组件可以访问它们,这些组件可能需要查询和突变。我希望能够轻松更新数据需求,这些数据需求将更新某些父组件查询的字段或父/兄弟/子项中的变异返回的字段,以便准确更新我的Apollo缓存。

我已经尝试创建一个全局高级graphql目录,其中所有的查询/ mutation.graphql文件都位于其中,#importing遍布我的应用程序的所有相关片段文件,然后直接导入它们,但这可能会变得单调乏味并且不会跟随父查询包含子片段的父/子主题。此外,在大型项目中,您最终会在导入时遍历长文件路径。

我也尝试过在全局graphql目录中创建与组件文件对应的片段文件,但是这并没有给出我正在寻找的“组件/数据要求”托管。

这有效:

class CommentListItem extends Component {
  static fragments = {
    comment: gql`
      #...
    `,
  }
}
class CommentList extends Component {
  static fragments = {
    comment: gql`
      #...
      ${CommentListItem.fragments.comment}
    `,
  }
}
class CommentsPage extends Component {
  static fragments = {
    comment: gql`
      #...
      ${CommentList.fragments.comment}
    `,
  }
}
graphql(gql`
  query Comments {
    comments {
      ...CommentsListItemComment
    }
  }
  ${CommentsPage.fragments.comment}
`)

但是,如果我想在CommentsPage的后代中发生突变,我就不能从CommentsPage.fragments.comment中引用片段组成。

这种类型的东西有优选的方法或最佳实践吗?

reactjs graphql apollo react-apollo
1个回答
6
投票

Structuring Queries

如何构建代码始终是个人品味的问题,但我认为查询和组件的搭配是GraphQL的一大优势。

对于查询,我从Relay Modern获得了很多灵感,解决方案看起来非常接近您在代码中描述的内容。现在,随着项目变得越来越大,我们想要为查询生成Flow类型定义,将它们放在组件文件旁边的单独文件中也是一种选择。这与CSS-modules非常相似。

Structuring Mutations

当谈到突变时,为它们寻找一个好地方通常会变得更加困难。需要在远离组件树的事件上调用突变,并且经常在应用程序的多个状态中更改应用程序的状态。在这种情况下,您希望调用者不知道数据使用者。使用片段似乎是一个简单的答案。突变将仅包括为特定类型定义的所有片段。虽然突变现在不需要知道哪些字段是必需的,但它需要知道谁需要该类型的字段。我想指出两种略有不同的方法,您可以使用这些方法来设计您的设计。

全球变异:接力方法

在Relay Modern Mutations are basically global operations中,可以由任何组件触发。这种方法并不坏,因为大多数突变只写一次,并且由于变量非常可重复使用。它们在一个全局状态下运行,并不关心哪个UI部分消耗更新。定义变异结果时,通常应查询可能由变异更改的属性,而不是其他组件(通过片段)所需的所有属性。例如。突变likeComment(id: ID!)可能应该在评论中查询likeCountlikes字段,如果任何组件在Comment上使用该字段或组件需要什么其他字段,则不在乎。当您必须更新其他查询或字段时,此方法会变得更加困难。变异createComment(comment: CreateCommentInput)可能想写入根查询对象的comments字段。这是节点和边缘的Relays结构派上用场的地方。您可以了解有关接力更新here的更多信息。

# A reusable likeComment mutation
mutation likeComment($id: ID!) {
  likeComment(id: $id) {
    comment {
      id
      likeCount
      likes {
        id
        liker {
          id
          name
        }
      }
    }
  }
}

不幸的是,我们无法回答一个问题:我们应该走多远?我是否需要喜欢评论的人的名字,或者组件是否只显示了许多喜欢的内容?

查询容器中的突变

并非所有GraphQL API都以Relay方式构建。此外,Apollo将突变绑定到商店,类似于Redux动作创建者。我目前的方法是在与查询相同的级别上进行突变,然后将它们传递下去。通过这种方式,您可以访问子项的片段,并在需要时在突变中使用它们。在您的示例中,CommentListItem组件可能会显示类似按钮。它将定义数据依赖性的片段,根据片段的prop类型和函数prop类型likeComment: (id: string) => Promise<any>。此prop类型将传递给查询容器,该容器将CommentsPage包装在查询和变异中。

摘要

您可以将这两种方法与Apollo一起使用。全局mutations文件夹可以包含可以在任何地方使用的突变。然后,您可以直接将突变绑定到需要它们的组件。一个好处是,例如,在likeComment示例中,变量id可以直接从组件props派生而来,不需要在组件本身内绑定。或者,您可以从查询组件中传递突变。这为您提供了更广泛的数据使用者概述。在CommentsPage中,可以更容易地确定突变完成时需要更新的内容。

让我知道你在评论中的想法!

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