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

Reactjs 如何将变量传递给GraphQL查询?,reactjs,react-apollo,Reactjs,React Apollo,假设我在React Apollo中有以下GraphQL查询 const CurrentUserForLayout = gql` query CurrentUserForLayout($avatarID: Int!) { currentUser { avatar_url(avatarID: $avatarID) } } `; const ProfileWithData = graphql(CurrentUserForLayout, { options: {

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

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

const ProfileWithData = graphql(CurrentUserForLayout, {
  options: { variables: { avatarID: 1 } },
})(Profile);
现在,如果我想让我的React组件
Profile
更改虚拟角色

我该怎么做

我不熟悉React和GraphQl,我不太理解这里的联系:

graphql(CurrentUserForLayout, {
      options: { variables: { avatarID: 1 } },
    })(Profile);
我真的需要
ProfileWithData

要将另一个
avatarID
传递给查询?但是,如果ID由配置文件组件操纵,我如何让父组件知道这一点呢?

您的
ProfileWithData
组件在呈现某个用户的化身方面做得很好。该组件不负责管理当前显示的化身组件的更改

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>
);
一种方法是添加一个新的道具
avatarId
,该道具从父组件传递下来。然后你需要写下:

graphql(CurrentUserForLayout, {
  options: (ownProps) => ({
    variables: {
      id: ownProps.avatarId
    }
  })
})(Profile);
如果您熟悉react router,另一种方法是使用路由参数来确定化身id。您需要调整
graphql
的调用,如下所示:

graphql(CurrentUserForLayout, {
  options: (ownProps) => ({
    variables: {
      id: ownProps.params.avatarId
    }
  })
})(Profile);

要了解更多关于此类查询变量的用法,可以查看。

到目前为止,我知道两种可能的方法

第一个问题已在问题中陈述。这些变量同时是
ProfileWithData
的支柱。因此,您需要找到一种方法来更改道具并重新播放组件。这通常是通过父组件实现的。因此,通常不会更改
ProfileWithData
中的变量。此组件应仅用于显示目的。然而,这并不是说它不能做到。可以将父组件的方法传递给子组件,以便操纵父组件的状态。这将重新渲染这两个组件,并使用新的道具/变量呈现
ProfileWithData

第二种方法是从
ProfileWithData
组件内部进行查询。然后,可以使用状态从组件内部操纵变量。可以找到这样做的方法

您可以通过使用
使用阿波罗
更高阶组件,如下所述:

然后,可以对传入的对象调用
client.query
,如下所示:

 class MyComponent extends React.Component {
      runQuery() {
        this.props.client.query({
          query: gql`...`,
          variables: { ... },
        });
      }

      render() { ... }
    }

    withApollo(MyComponent);

阿波罗客户端2.1版之前

在Apollo Client 2.1之前,当您必须使用(HOCs)时,henk在另一个答案中正确地指出了两种解决方案。我试着简单总结一下:

  • 由于HOC只能访问props,因此需要在父组件中引入不断变化的变量。例如,父组件可以使用React的
    setState()
    方法为不断变化的变量设置本地状态管理。一旦变量在本地状态中发生更改,它就可以传递给其他组件,而该组件由HOC增强。HOC可以访问props,并可以使用更改的变量执行查询。提示:如果您不想在两者之间引入另一个组件来更改本地状态,“s
    with state
    HOC可能是一个不错的选择

  • 第二种方法是使用
    withApollo()
    HOC,它允许您作为道具访问Apollo客户端实例,因为它将您的代码从声明式转换为命令式。在React组件中有了这个实例,一旦变量发生变化,就可以在组件的一个类方法(例如
    onChange
    handler)中调用
    client.query({query:…,variables:…})

自阿波罗客户端2.1以来

因为您可以使用新的查询(和变异)组件。虽然HOC仍然存在,但不再由发布广告。但是,新的查询(和变异)组件在您的组件中使用。它使用React的渲染道具模式

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>
);
从“React”导入React;
从“react apollo”导入{Query};
从“graphql标签”导入gql;
const GET_TODOS=gql`
{
待办事项{
身份证件
类型
}
}
`;
常数Todos=()=>(
{({加载,错误,数据})=>{
如果(加载)返回加载…

; if(error)返回错误:(

; 返回data.todos.map(({id,type})=>(

{type}

)); }} );
通过在组件内部移动此控制流,而不是仅将其与HOC放在同一位置,可以将更改的属性作为变量传递给查询(和变异)组件

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>
);
从“React”导入React;
从“反应阿波罗”中导入{突变};
从“graphql标签”导入gql;
const TOGGLE_TODO=gql`
突变切换到($id:Int!){
toggleTodo(id:$id){
身份证件
完整的
}
}
`;
常量Todo=({id,text})=>(
{(toggleTodo,{加载,错误,数据})=>(

{text}

{加载和加载…

} {错误&&错误:(请重试

} )} );

如果您想在React,checkout中学习Apollo Client。注意:代码片段取自Apollo Client 2.1发行版的博客文章。

使用上述答案中给出的查询组件或您提到的方法哪个更好?我对graphql非常陌生。