我正在使用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
引用片段组成 .
这种类型的东西有优选的方法或最佳实践吗?
1 回答
构造查询
如何构建代码始终是个人品味的问题,但我认为查询和组件的搭配是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的更多信息 .不幸的是,我们无法回答一个问题:我们应该走多远?我是否需要喜欢评论的人的名字,或者组件是否只显示了许多喜欢的内容?
查询容器中的突变
并非所有GraphQL API都采用Relay方式构建 . 此外,Apollo将突变绑定到商店,类似于Redux动作创建者 . 我目前的方法是在与查询相同的级别上进行突变,然后将它们传递下去 . 通过这种方式,您可以访问子代的片段,并在需要时将其用于突变中 . 在您的示例中,
CommentListItem
组件可能会显示类似按钮 . 它将为数据依赖关系定义一个片段,根据片段定义类型和函数prop类型likeComment: (id: string) => Promise<any>
. 此prop类型将传递给查询容器,该查询容器将CommentsPage
包装在查询和变异中 .摘要
您可以将这两种方法与Apollo一起使用 . 全局
mutations
文件夹可以包含可在任何地方使用的突变 . 然后,您可以直接将突变绑定到需要它们的组件 . 一个好处是,例如在likeComment
示例中,变量id
可以直接从组件props派生,而不需要在组件本身内绑定 . 或者,您可以从查询组件中传递突变 . 这给你一个更广泛的数据消费者概述 . 在CommentsPage
中,可以更容易地确定突变完成时需要更新的内容 .让我知道你在评论中的想法!