通过 compose( graphql() ) 手动触发查询

Posted

技术标签:

【中文标题】通过 compose( graphql() ) 手动触发查询【英文标题】:Manually fire a query via compose( graphql() ) 【发布时间】:2019-11-03 01:58:15 【问题描述】:

我是 Apollo 和 graphql 的新手,我正在尝试使用 shopify 的店面 API 设置一个电子商务网站。该网站是用 react 和 Next.js 构建的,用于 s-s-r。

我已经设法获得了一些样板代码,用于与 shopify 进行基本的购物车交互。我有一个包装整个应用程序的 Page 组件,它位于 ApolloProvider 下方,可以访问 apollo 客户端。目前我正在使用 compose() 为我的 Page 组件提供一些 graphql (taken from this example):

const pageWithData = compose(
  graphql(query), // Query that retrieves base shopify information, such as shop name, description and products
  graphql(createCheckout, name: "createCheckout"), // Mutation that creates a new checkout object with shopify. Basically a cart object
  graphql(checkoutLineItemsAdd, name: "checkoutLineItemsAdd"), // Mutation that adds a new lineitem to the checkout object
  graphql(checkoutLineItemsUpdate, name: "checkoutLineItemsUpdate"), // Mutation that updates a line item
  graphql(checkoutLineItemsRemove, name: "checkoutLineItemsRemove"), // Mutation that removes a lineitem
)(Page);

这一切都按预期工作,除了当我刷新浏览器时,购物车被清空,并创建了一个新的结帐对象。所以我想要做的是将结帐 ID 存储在 localStorage 中,并在创建新的结帐对象之前检查 localstorage 中是否有 ID。如果有,我将加载该结帐。现在结帐是在页面组件中创建的:

componentWillMount() 
    this.props.createCheckout(
        variables: 
            input: 
        ).then((res) => 
        this.setState(
            checkout: res.data.checkoutCreate.checkout
        );
    );

现在,我找到了一个有效的 graphql 查询来加载基于 ID 的现有结帐:

const checkoutFetchQuery = gql`
  query checkoutFetch ($checkoutId: ID!) 
      node(id: $checkoutId) 
        ... on Checkout 
          webUrl
          subtotalPrice
          totalTax
          totalPrice
          lineItems (first:250) 
            pageInfo 
              hasNextPage
              hasPreviousPage
            
            edges 
              node 
                title
                variant 
                  title
                  image 
                    src
                  
                  price
                
                quantity
              
            
          
        
      
    
`;

所以我想我可以像这样简单地将它添加到 compose 方法中:

const pageWithData = compose(
  graphql(query), // Query that retrieves base shopify information, such as shop name, description and products

  graphql(checkoutFetchQuery,  name: "fetchCheckout"), // Query that fetches checkout based on a checkoutID

  graphql(createCheckout, name: "createCheckout"), // Mutation that creates a new checkout object with shopify. Basically a cart object
  graphql(checkoutLineItemsAdd, name: "checkoutLineItemsAdd"), // Mutation that adds a new lineitem to the checkout object
  graphql(checkoutLineItemsUpdate, name: "checkoutLineItemsUpdate"), // Mutation that updates a line item
  graphql(checkoutLineItemsRemove, name: "checkoutLineItemsRemove"), // Mutation that removes a lineitem
)(Page);

但这会导致 Apollo 开发工具出现以下错误:

GraphQL Errors: Variable checkoutId of type ID! was provided invalid value

我确定这是我不理解 compose() 如何在 react-apollo 中工作的一些关键概念。我知道我需要为查询提供一些变量,但由于某种原因,这个查询似乎在加载时立即运行,正如我所期望的那样,这只会使查询在组件上可用。其他一些 graphql() 语句也需要变量,例如“checkoutLineItemsAdd”,但这不会导致错误。我注意到的另一件事是突变作为函数添加到组件道具中,而我的查询被添加为对象。

我正在努力寻找任何好的文档。

查询会立即运行吗? 是否正在等待从组件调用突变,从而允许我们动态添加变量? 我是否应该以不同的方式编写我的 gql 语法以使其成为组件上的函数而不是对象? 当附加到 compose HOC 时,我们如何将变量动态传递给查询? 为什么我从这个查询中得到错误,而不是突变,在运行之前也需要变量?

【问题讨论】:

【参考方案1】:

您的查询需要输入checkoutId,其类型为ID

但是您的查询graphql(checkoutFetchQuery, name: "fetchCheckout") 正在被触发而没有任何输入。您可以通过这样做添加输入变量

graphql(checkoutFetchQuery, 
  name: "fetchCheckout",
  options: 
    variables: 
      checkoutId: localstorage.get('checkoutid')
    
  
)

选项配置的文档是here

您还可以通过在以下选项下添加跳过检查来跳过自动触发查询

options: 
  skip: !localstorage.get('checkoutid')

【讨论】:

谢谢约翰尼,但如果这是用户第一次访问怎么办。那么localstorage中还没有checkoutID。我需要能够首先检查它,可能在 componentWillMount 钩子中。是否可以推迟触发查询,直到从 component.props 调用它? 我,编辑了答案。如果你想要类似于突变的东西,那么你将不得不使用 apollo 客户端手动触发查询。 哦,哇,您刚刚编辑并回答了我的评论。谢谢 :)。不过后续问题:如果我跳过它,我是否可以使用变量手动触发它? 啊,我明白了。以及如何从子组件手动访问客户端? 的子级 你能在这里加入聊天吗chat.***.com/rooms/195256/gql

以上是关于通过 compose( graphql() ) 手动触发查询的主要内容,如果未能解决你的问题,请参考以下文章

如何将两个依赖的 GraphQL 查询与“compose”结合起来?

graphql-compose 在解析方法中不接受我的参数

hasura graphql-engine &&patroni docker-compose 环境运行

如何测试graphql apollo组件?如何在 compose() 中获得完整的覆盖?

使用 graphql-compose-mongoose 将对象添加到 mongodb 模型中的对象数组

metabase docker-compose 运行说明