我正在使用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
引用片段组成。
对于这类事物,是否有首选方法或最佳做法?
答案 0 :(得分:6)
如何构建代码始终是个人品味的问题,但我认为查询和组件的搭配是GraphQL的一大优势。
对于查询,我从Relay Modern中获得了很多灵感,解决方案看起来非常接近您在代码中描述的内容。现在,随着项目变得越来越大,我们想要为查询生成Flow类型定义,将它们放在组件文件旁边的单独文件中也是一种选择。这与CSS-modules非常相似。
当涉及到突变时,为它们找到一个好地方往往要困难得多。需要在远离组件树的事件上调用突变,并且经常在应用程序的多个状态中更改应用程序的状态。在这种情况下,您希望调用者不知道数据使用者。使用片段似乎是一个简单的答案。突变将仅包括为特定类型定义的所有片段。虽然突变现在不需要知道哪些字段是必需的,但它需要知道谁需要该类型的字段。我想指出两种稍微不同的方法,您可以使用这些方法来设计。
在Relay Modern Mutations are basically global operations中,可以由任何组件触发。这种方法并不坏,因为大多数突变只写一次,并且由于变量非常可重复使用。它们在一个全局状态下运行,并不关心哪个UI部分消耗更新。定义变异结果时,通常应查询可能由变异更改的属性,而不是其他组件(通过片段)所需的所有属性。例如。变异likeComment(id: ID!)
可能应该在评论中查询likeCount
和likes
字段,如果任何组件完全使用该字段或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类型likeComment: (id: string) => Promise<any>
定义prop类型。此prop类型将传递给查询容器,该容器将CommentsPage
包装在查询和变异中。
您可以将这两种方法与Apollo一起使用。全局mutations
文件夹可以包含可在任何地方使用的突变。然后,您可以直接将突变绑定到需要它们的组件。一个好处是,例如,在likeComment
示例中,变量id
可以直接从组件props派生而来,不需要在组件本身内绑定。或者,您可以从查询组件中传递突变。这为您提供了更广泛的数据使用者概述。在CommentsPage
中,可以更容易地确定突变完成时需要更新的内容。
让我知道你在评论中的想法!