web-dev-qa-db-ja.com

変数をGraphQLクエリに渡す方法は?

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 component ProfileにavatarIDを変更させたい場合は、

どうすればいいですか

私はReactとGraphQlに不慣れで、ここでの関係を本当に理解していません:

graphql(CurrentUserForLayout, {
      options: { variables: { avatarID: 1 } },
    })(Profile);

別のProfileWithDataをクエリに渡すには、本当にavatarIDの周りに別の親コンポーネントが必要ですか?しかし、IDがプロファイルコンポーネントによって操作された場合、どうしたら親コンポーネントにそれを知らせることができますか?

11
henk

これまでのところ、これに対する2つの可能なアプローチを知っています。

最初のはすでに質問で述べられています。変数は同時にProfileWithDataの小道具です。したがって、小道具を変更してコンポーネントを再レンダリングする方法を見つける必要があります。これは通常、親コンポーネントで実現されます。したがって、通常はProfileWithData内の変数を変更しません。このコンポーネントは、表示目的でのみ使用してください。しかし、これはそれができないということではありません。親の状態を操作するために、親コンポーネントのメソッドを子に渡すことができます。これにより、両方のコンポーネントが再レンダリングされ、ProfileWithDataが新しい小道具/変数でレンダリングされます。

2番目のアプローチは、ProfileWithDataコンポーネントの内部からクエリを実行することです。その後、状態を使用してコンポーネントの内部から変数を操作できます。これを行う方法は次のとおりです here

ここに記載されているように、withApollo高次コンポーネントを使用してApolloクライアントへの参照を渡すことにより、これを行うことができます。 http://dev.apollodata.com/react/higher-order-components .html#withApollo

次に、渡されたオブジェクトに対してclient.queryを次のように呼び出すことができます。

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

      render() { ... }
    }

    withApollo(MyComponent);
2
henk

Apolloクライアント2.1以前

Apollo Client 2.1より前は、 Higher-Order Components (HOCs)を使用する必要がある場合、他の回答でhenkによって正しく指摘された2つのソリューションがありました。私はそれらを簡単に要約しようとします:

  • HOCは小道具にのみアクセスできるため、親コンポーネントに変更変数を導入する必要があります。たとえば、親コンポーネントは、ReactのsetState()メソッドを使用して、変化する変数に対して適切なローカル状態管理を行うことができます。変数がローカル状態で変化すると、HOCによって拡張される他のコンポーネントに渡すことができます。 HOCは小道具にアクセスでき、変更された変数でクエリを実行できます。 ヒント:ローカル状態を変更するために間に別のコンポーネントを導入したくない場合は、 recomposewithState HOCが最適です。

  • 2番目の方法ですが、コードが宣言型から命令型にシフトするため、あまりエレガントではない方法ですが、withApollo() HOCを使用して、Apolloクライアントインスタンスにpropとしてアクセスできます。このインスタンスをReactコンポーネントに含めると、変数が変更されたら、コンポーネントのクラスメソッドの1つ(たとえば、onChangeハンドラー)でclient.query({ query: ..., variables: ... })を呼び出すことができます。

Apolloクライアント2.1以降

Apollo Client 2.1 以降、新しいクエリ(およびミューテーション)コンポーネントを使用できます。 HOCはまだ存在しますが、 documentation によって宣伝されなくなりました。ただし、新しいクエリ(およびミューテーション)コンポーネントはコンポーネント内で使用されます。 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>
);

この制御フローをHOCと同じ場所に配置するだけでなく、コンポーネント内でシフトすることにより、変更するプロップを変数としてQuery(および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>
);

ReactでApolloクライアントを学びたい場合は、 この広範なチュートリアル をチェックしてください。注:コードスニペットは、Apollo Client 2.1リリースのブログ投稿から取得されました。

7
Robin Wieruch

ProfileWithDataコンポーネントは、特定のユーザーのアバターを適切にレンダリングします。現在表示されているアバターコンポーネントの変更を管理することは、このコンポーネントの責任ではありません。

1つの方法は、親コンポーネントから渡される新しいprop avatarIdを追加することです。次に、これを書く必要があります:

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

react-routerに慣れている場合は、ルートパラメータを使用してアバターIDを特定することもできます。 graphqlの呼び出しを次のように調整する必要があります。

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

このようなクエリ変数の使用方法の詳細については、 React Track of Learn Apollo を確認してください。

5
marktani