我可以在片段上使用指令并有条件地调用它的变量吗?

gol*_*und 2 reactjs graphql react-apollo

我正在开发一个允许用户上传大型数据集的应用程序。上传者有一个“草稿”版本,他们可以在 UI 中编辑该版本,然后他们发布草稿的快照,所有用户都可以看到。仅当上传者登录时才应查询草稿文件。

虽然非编辑权限用户看不到草稿,但该应用程序仍会查询其整个文件集,这使得获取数据集页面非常缓慢。

该查询具有“草稿”数据的片段,包括有条件不想要的文件。如果我省略片段中的文件,则该组件适用于所有用户……但是上传者无法获取他们的草稿文件。所以这该死的,如果我这样做,该死的如果我不犹豫,我对 graphql 和 apollo 缺乏经验在这里真的很闪耀。

这是查询和随附的钩子:

export const getDatasetPage = gql`
  query dataset($datasetId: ID!) {
    dataset(id: $datasetId) {
      id
      created
      public
      following
      starred
      ...DatasetDraft
      ...DatasetPermissions
      ...DatasetSnapshots
      ...DatasetIssues
      ...DatasetMetadata
      ...DatasetComments
      uploader {
        id
        name
        email
      }
      analytics {
        downloads
        views
      }
      onBrainlife
    }
  }
  ${DatasetQueryFragments.DRAFT_FRAGMENT}
  ${DatasetQueryFragments.PERMISSION_FRAGMENT}
  ${DatasetQueryFragments.DATASET_SNAPSHOTS}
  ${DatasetQueryFragments.DATASET_ISSUES}
  ${DatasetQueryFragments.DATASET_METADATA}
  ${DATASET_COMMENTS}
`

export const DatasetQueryHook = ({ datasetId }) => {
  const {
    data: { dataset },
    loading,
    error,
  } = useQuery(getDatasetPage, {
    variables: { datasetId },
  })
  if (loading) {
    return <Spinner text="Loading Dataset" active />
  } else {
    if (error) Sentry.captureException(error)
    return (
      <ErrorBoundary error={error} subject={'error in dataset page'}>
        <DatasetQueryContext.Provider
          value={{
            datasetId,
          }}>
          <DatasetPage dataset={dataset} />
        </DatasetQueryContext.Provider>
      </ErrorBoundary>
    )
  }
}
Run Code Online (Sandbox Code Playgroud)

这是片段:

export const DRAFT_FRAGMENT = gql`
  fragment DatasetDraft on Dataset {
    id
    draft {
      id
      modified
      readme
      partial
      description {
        Name
        Authors
        DatasetDOI
        License
        Acknowledgements
        HowToAcknowledge
        Funding
        ReferencesAndLinks
      }
      files {    //when this is removed, it works...except for users with edit privileges
        id
        filename
        size
      }
      summary {
        modalities
        sessions
        subjects
        subjectMetadata {
          participantId
          age
          sex
          group
        }
        tasks
        size
        totalFiles
        dataProcessed
      }
    }
  }
`
Run Code Online (Sandbox Code Playgroud)

长话短说:如果用户没有编辑权限,查询应该省略草稿文件。我知道 hasEdit 的逻辑,但我不知道如何使用指令来实现它。我什至可以@skip在片段上使用,即使可以,我可以有条件地传递它的变量吗?我在文档中找不到任何关于此的内容,并且对解决方案感到茫然。

Dan*_*den 7

是的,指令可以在片段内使用,是的,您可以为此使用变量。

下面是一个使用 SWAPI API的简单示例

query MyQuery ($showDate: Boolean!){
  allFilms {
    films {
      ...FilmFields
    }
  }
}

fragment FilmFields on Film {
  id
  title
  releaseDate @include(if: $showDate)
}
Run Code Online (Sandbox Code Playgroud)

这里要注意的一件事是变量仍然被定义为操作的一部分。这意味着如果您将片段放在单独的文件中,然后将它们导入到查询中,则需要确保 A) 操作实际定义了变量,并且 B) 变量的名称是正确的。

奖金

另外值得注意的是,有实验支持将变量定义为片段的一部分。这必须在服务器端显式启用。如果您使用的是 graphql-tag,则还必须在那里显式启用它。如果您使用的是makeExecutableSchemaApollo Server,则可以传入一个parseOptions参数来启用此功能服务器端:

makeExecutableSchema({
  typeDefs,
  resolvers,
  parseOptions: {
    experimentalFragmentVariables: true,
  },
})
Run Code Online (Sandbox Code Playgroud)

然后你可以创建片段,如:

fragment FilmFields on Film ($showDate: Boolean!) {
  id
  title
  releaseDate @include(if: $showDate)
}
Run Code Online (Sandbox Code Playgroud)