如何将变量传递给GraphQL查询?

hen*_*enk 11 reactjs react-apollo

让我们假设我在React-Apollo中有以下GraphQL查询

const CurrentUserForLayout = gql`
  query CurrentUserForLayout($avatarID: Int!) {
    currentUser {
      avatar_url(avatarID: $avatarID)
    }
  }
`;

const ProfileWithData = graphql(CurrentUserForLayout, {
  options: { variables: { avatarID: 1 } },
})(Profile);
Run Code Online (Sandbox Code Playgroud)

现在,如果我想让我的React组件Profile更改avatarID,

我该怎么办?

我是React和GraphQl的新手,我不太明白这里的连接:

graphql(CurrentUserForLayout, {
      options: { variables: { avatarID: 1 } },
    })(Profile);
Run Code Online (Sandbox Code Playgroud)

我真的需要另一个父组件ProfileWithData 来传递另一个父组件avatarID吗?但是,如果ID由Profile组件操纵,我如何让Parent组件知道呢?

Rob*_*uch 8

在Apollo Client 2.1之前

在Apollo Client 2.1之前,必须使用高阶组件(HOC)时,有两个解决方案由henk在另一个答案中正确指出。我尝试简要地总结一下:

  • 由于HOC只能访问道具,因此您需要在父组件中引入更改变量。例如,父组件可以使用React setState()方法对更改的变量进行本地状态管理。一旦变量在本地状态中更改,就可以将其向下传递到由HOC增强的其他组件。HOC可以访问道具,并且可以使用更改后的变量执行查询。提示:如果您不想在两者之间引入其他组件来更改本地状态,则重新组合withStateHOC可能是一个不错的选择。

  • 第二种方法(但可能不太优雅)是因为它会将代码从声明式转换为命令式,因此将使用withApollo()HOC,它使您可以访问Apollo Client实例。在React组件中拥有此实例后,一旦变量更改,就可以调用client.query({ query: ..., variables: ... })组件的类方法之一(例如,onChange处理程序)。

从Apollo Client 2.1开始

Apollo Client 2.1开始,您可以使用新的查询(和突变)组件。但是,HOC仍然存在,但不再由文档发布。但是,您的组件中使用了新的查询(和突变)组件。它使用React的render props模式。

import React from "react";
import { Query } from "react-apollo";
import gql from "graphql-tag";

const GET_TODOS = gql`
  {
    todos {
      id
      type
    }
  }
`;

const Todos = () => (
  <Query query={GET_TODOS}>
    {({ loading, error, data }) => {
      if (loading) return <p>Loading...</p>;
      if (error) return <p>Error :(</p>;

      return data.todos.map(({ id, type }) => (
        <p key={id}>{type}</p>
      ));
    }}
  </Query>
);
Run Code Online (Sandbox Code Playgroud)

通过将控制流转移到组件内部,而不是仅将其与HOC放在同一位置,您可以将更改的prop作为变量传递给查询(和Mutation)组件。

import React from "react";
import { Mutation } from "react-apollo";
import gql from "graphql-tag";

const TOGGLE_TODO = gql`
  mutation ToggleTodo($id: Int!) {
    toggleTodo(id: $id) {
      id
      completed
    }
  }
`;

const Todo = ({ id, text }) => (
  <Mutation mutation={TOGGLE_TODO} variables={{ id }}>
    {(toggleTodo, { loading, error, data }) => (
      <div>
        <p onClick={toggleTodo}>
          {text}
        </p>
        {loading && <p>Loading...</p>}
        {error && <p>Error :( Please try again</p>}
      </div>
    )}
  </Mutation>
);
Run Code Online (Sandbox Code Playgroud)

如果您想在React中学习Apollo Client,请阅读本教程。注意:代码段摘自Apollo Client 2.1版本的博客文章。


mar*_*ani 5

您的ProfileWithData组件可以很好地呈现特定用户的头像。管理当前显示的头像组件的更改不是此组件的责任。

一种方法是添加avatarId从上级组件传递下来的新道具。然后,您需要编写以下代码:

graphql(CurrentUserForLayout, {
  options: (ownProps) => ({
    variables: {
      id: ownProps.avatarId
    }
  })
})(Profile);
Run Code Online (Sandbox Code Playgroud)

如果您熟悉react-router,另一种方法是使用route参数来确定化身ID。您需要graphql像这样调整调用:

graphql(CurrentUserForLayout, {
  options: (ownProps) => ({
    variables: {
      id: ownProps.params.avatarId
    }
  })
})(Profile);
Run Code Online (Sandbox Code Playgroud)

要了解更多有关查询变量用法的信息,您可以查看React Acadelo学习轨迹