如何在使用表单组件时在 apollo-client 中链接突变

Posted

技术标签:

【中文标题】如何在使用表单组件时在 apollo-client 中链接突变【英文标题】:How to chain mutations in apollo-client while using a form component 【发布时间】:2019-06-17 11:48:17 【问题描述】:

阿波罗客户端 2.0。我正在使用链式突变组件。我正在尝试将第一个 Mutation 的返回值传递给第二个 Mutation。当单击表单组件上的 onSubmit 按钮时,我执行突变。第一个突变的返回值没有作为第二个突变中的“变量”之一传递

我在两个非常相似的帖子中查看了解决方案:How to wrap GraphQL mutation in Apollo client mutation component in React 和 How to chain together Mutations in apollo client。我认为我对表单的使用为我的解决方案增加了一些额外的复杂性。尽管传递的值(competitionId)在 handleOnSubmit 函数中可见(如果我在 handleOnSubmit 中的 createCompetition() 之后进行控制台日志),但它不会作为在 handleOnSubmit 中调用的第二个 Mutation 中的变量传递。结果是第一个 Mutation 成功执行,第二个 Mutation 出现 400 错误:“errors”:[“message”:“Variable \“$competitionId\” of required type \“ID!\”没有提供。 ”更具体地说, CompetitionId 的值在第一个突变运行后会传递给第二个突变,但它不会作为“变量”传递给作为参数传递给 handleOnSubmit 的 createMatch 函数。看起来与 createMatch 函数一起传递给 handleOnSubmit 的“变量”仅包括单击提交按钮时可用的变量。在点击提交按钮后生成competitionId,第一个mutation将其作为结果返回。

handleOnSubmit = async(event, createCompetition, createMatch) => 
event.preventDefault();
await createCompetition();
await createMatch();
this.clearState();
this.props.history.push('/home');

render () 
const location, name, action, caliber, rifleName, dateOf,competitionScore = this.state;
const  matchNumber, targetNumber, relay, distanceToTarget, matchScore = this.state;
return (
<div className="App">
  <h2 className="App">Add Competition</h2>
  <Mutation 
    mutation=CREATE_COMPETITION 
    variables=location, name, action, caliber, rifleName, dateOf, competitionScore
    refetchQueries=() => [
       query: GET_ALL_COMPETITIONS, variables:name: name
    ]
    update=this.updateCache>
    (createCompetition, data, loading, error) => 

      if(loading) return <div>loading competition...</div>
      if(error) return <div>error: error</div>
      let competitionId;
      if(data) 
        competitionId = data.createCompetition._id;
      
      return (
        <Mutation
          mutation=CREATE_MATCH
          variables=competitionId, matchNumber, targetNumber, distanceToTarget, matchScore>
          (createMatch, _, loading, error) => 
            if(loading) return <div>loading match...</div>
            return (
              <form 
                className="form" 
                onSubmit=event => this.handleOnSubmit (event, createCompetition, createMatch)>
                <label>  remaining form deleted for brevity

我希望 CompetitionId 的值作为变量传递给在 handleOnSubmit 方法中调用的 createMatch 函数。没有提供。

【问题讨论】:

【参考方案1】:

看来你需要的是嵌套突变 :thinkingface;

问:你在使用 prisma 吗?

嗯,在 GraphQL 中,您可以通过单个突变创建节点,如果您的类型相关,这非常简单,所以我假设这是您的情况。

看起来应该是这样的:

datamodel.graphql

type Competition 
  id: ID! @unique
  name: String!
  match: Match! @relation(name: "CompetitionMatch")


type Match 
  id: ID! @unique
  name: String!
  campetition: Competition! @relation(name: "CompetitionMatch")

所以,现在你的schema.graphql 应该是这样的:

type Mutation 
  createCompetition (name: String! match: MatchInput): Competition


input MatchInput 
  name: String!

现在当您调用 createCompetition 突变时,您必须发送匹配数据,如下所示:

mutation createCompetition (
 name: 'Loremp competition'
 match:  name: 'child match'
) 
 id
 name
 match 
  id
  name
 

参考:https://www.graph.cool/docs/reference/graphql-api/mutation-api-ol0yuoz6go/#nested-create-mutations

希望对您有所帮助!

问候

【讨论】:

我没有使用棱镜。我更愿意继续使用 Apollo-Server 2 和 mongoose。一旦我更好地理解了 Apollo-Server/Client,我可能会尝试 prisma。您对我的类型相关的假设是正确的并且查询工作正常,这是一个挑战: type Competition _id: ID name: StringrifleName: String location: String action: String caliber: Float dateOf: String CompetitionScore: String匹配:[匹配] `; 我通过在后端编写一个支持模式的更复杂的突变解决了这个问题。然后我所要做的就是调用单个突变,不需要链接。我收到了在我们当地的 React MeetUp 上尝试这种技术的建议。在研究了这一点后,我将 Apollo 文档中提供的指导铭记于心。该指导是您应该根据客户如何最好地使用数据来编写特定的突变/查询。我在后端 API 上编写了一个突变,创建了一个比赛、3 场比赛和 60 次投篮。【参考方案2】:

如果(数据)在哪里,你应该在哪里返回第二个突变

【讨论】:

以上是关于如何在使用表单组件时在 apollo-client 中链接突变的主要内容,如果未能解决你的问题,请参考以下文章

使用 ng-content 时在表单验证中不考虑输入

在 Apollo-client 中,writeQuery 会更新缓存,但 UI 组件不会重新渲染

GraphQL _ Apollo-client - 直接在组件中传递 guery 变量

如何在运行时在表单生成器中使用 I18n 和 Json Schema?

无法理解 apollo-client 中解析器的使用

我可以在运行时在 netbeans 的 jframe 中添加一个组件吗?