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がプロファイルコンポーネントによって操作された場合、どうしたら親コンポーネントにそれを知らせることができますか?
これまでのところ、これに対する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);
Apolloクライアント2.1以前
Apollo Client 2.1より前は、 Higher-Order Components (HOCs)を使用する必要がある場合、他の回答でhenkによって正しく指摘された2つのソリューションがありました。私はそれらを簡単に要約しようとします:
HOCは小道具にのみアクセスできるため、親コンポーネントに変更変数を導入する必要があります。たとえば、親コンポーネントは、ReactのsetState()
メソッドを使用して、変化する変数に対して適切なローカル状態管理を行うことができます。変数がローカル状態で変化すると、HOCによって拡張される他のコンポーネントに渡すことができます。 HOCは小道具にアクセスでき、変更された変数でクエリを実行できます。 ヒント:ローカル状態を変更するために間に別のコンポーネントを導入したくない場合は、 recompose のwithState
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リリースのブログ投稿から取得されました。
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 を確認してください。