听说Relay有时会发出节点查询

这篇文章的总结

    • Relay GraphQL Clientがnodeクエリを利用し、NodeResolverをコールするタイミングを明らかにした。

@refetchableを利用すると、relay-compilerが、nodeクエリを利用するようなクエリを生成することがある。
RefetchableFragmentを利用しない場合、nodeクエリと、NodeResvolerは不要になる(と思われる)。

背景 – 背景

Node是指具有全局唯一标识的接口。
为了使GraphQL客户端能够进行缓存和数据重新获取,建议在每个GraphQL对象中实现Node接口,如下所示。

interface Node {
  id: ID!
}

# Nodeを実装したオブジェクトの例
type MyObject implements Node {
  id: ID!
  name: String!
}

这件事也写在下面的页面上。

 

然而,仅仅实现了Node并不足够,需要按照以下方式指定节点查询到模式中1。此外,有查询需求就必须实现解析器(由于这是关于服务器端的讨论,所以不涉及解析器的内部实现)。

type Query {
  node(id: ID!): Node
}

But here, one question arises. Usually, the client side bears… 但是,这里产生一个问题。通常情况下,客户端承担着…

query PageQuery {
  myObject {
    id
    name
  }
}

即使有时会写类似的代码,

query PageQuery($id: ID!) {
  node(id: $id) {
    name
  }
}

直接写入节点查询通常不是基本的操作,是吗?因此,我想知道在什么时候会发出该节点查询,或者实际上是否会发出该查询,所以我进行了调查。

进行了调查

首先,我天真地从Relay的问题页面上提交了一个问题。

 

然后,我被引导到了以下的页面。

 

经过查阅页面内容,我了解到refetch在使用时是怎么被使用的,但是直到我得到确切证实仍然不够确定。因此,我决定实际动手运行一下样本。由于设置比较麻烦,我打算使用Next.js来创建样本。

首先,在pages/index.tsx中准备查询主体和可重新查询的查询。假设已经完成了Relay和Next.js的设置。

const query = graphql`
  query pagesIndexQuery {
    myObject {
      id
      name
      ...pagesIndexFragment
    }
  }
`

const fragment = graphql`
  fragment pagesIndexFragment on MyObject 
    @refetchable(queryName: "RefetchQuery") {
      id
      name
  }
`

在这里,我们进行了pnpm build,并检查了自动生成的RefetchQuery.graphql.ts文件。通过查看第120行左右的params.text,我们确实可以确认已生成了node查询。

"query RefetchQuery(\n  $id: ID!\n) {\n  node(id: $id) {\n    __typename\n    ...pagesIndexFragment (以下省略)

接下来,我们将创建组件和服务器,并确认实际上是否会调用NodeResolver。我们将修改前面的pages/index.tsx如下。

import { graphql, useLazyLoadQuery, useRefetchableFragment } from "react-relay"
import { pagesIndexQuery } from "@/queries/__generated__/pagesIndexQuery.graphql"

const query = graphql`
  query pagesIndexQuery {
    myObject {
      id
      name
      ...pagesIndexFragment
    }
  }
`

const fragment = graphql`
  fragment pagesIndexFragment on MyObject @refetchable(queryName: "RefetchQuery") {
    id
    name
  }
`

export default function Index() {
  const data = useLazyLoadQuery<pagesIndexQuery>(query, {})
  const [_, refetch] = useRefetchableFragment(fragment, data.myObject)
  
  const onClick = () => {
    refetch({})
  }
  
  return (
    <main>
      <div>{JSON.stringify(data)}</div>
      <button onClick={onClick}>
        refetch
      </button>
    </main>
  )
}

画面看起来就是这个样子啊。

スクリーンショット 2023-12-03 20.51.03.png

 

我会立即敲门。
在页面加载时会触发Page查询,因此不会使用node。

スクリーンショット 2023-12-03 20.49.02.png

然而,当点击更新按钮时进行的重新获取(refetch)时,可以确认会发起节点查询,并且会使用NodeResolver。

スクリーンショット 2023-12-03 20.49.19.png

样本代码在这里。

    • Sample Server

 

    Sample Client

总结(再列举)

    • Relay GraphQL Clientがnodeクエリを利用し、NodeResolverをコールするタイミングを明らかにした。

@refetchableを利用すると、relay-compilerが、nodeクエリを利用するようなクエリを生成することがある。
RefetchableFragmentを利用しない場合、nodeクエリと、NodeResvolerは不要になる(と思われる)。

如果你有关于在这个情况下会发出node查询的信息,请一定与我们分享,我们会非常感激。

GraphQL Server Specification通过实现node查询,作者认为需要这个查询。Relay官方并没有明确说明。↩
广告
将在 10 秒后关闭
bannerAds