こんにちは、みんな、
apollo-link-restを使用してRESTAPIにアクセスしたいのですが、useQuery()ごとにresponse.headers
アクセスすることはできません。
たとえば、ページ付けを使用したREST APIは、ヘッダーにfirst, prev, next, last
情報を配置します。 どうすればそれにアクセスできますか?
開発ツールのNetwork
タブに移動し、ヘッダー付きの応答を参照しリンクには、ページネーション情報があります。 しかし、 Headers
にアクセスする方法がわかりません...。
Hierが私のメインコードです。 response.headers.link
を取得する方法がわかりません...
const queryTodos = gql`
query Todos($page: number, $limit: number) {
todos(_page: $page, _limit: $limit)
@rest(type: "[Todo]", path: "/todos/?{args}") {
userId
id
title
completed
}
}
`;
export const Todos = () => {
const { data, loading, error } = useQuery(queryTodos, {
variables: { page: 1, limit: 3 },
fetchPolicy: "no-cache"
});
...
return (<div>...</div>)
また、stackoverflowでこの質問をしました: https :
@ blatoo-残念ながら、これは現在apollo-link-restには存在しない機能です。
基本的に、GraphQLはヘッダーを処理することを期待していません-ヘッダーはグラフの奥深くで返される必要があるためです。
誰かがこれを実装したい場合、応答の「本体」にシークレット/自動フィールドとして__headers
を追加するのを見ることができますが、この動作を有効にするには機能フラグを追加する必要があります。 graphqlと互換性があるように、ヘッダーキーにいくつかのマングリングを行います。
const queryTodos = gql`
query Todos($page: number, $limit: number) {
todos(_page: $page, _limit: $limit)
@rest(type: "[Todo]", path: "/todos/?{args}") {
+ __headers {
+ XMyHeader
+ }
userId
id
title
completed
}
}
`;
@fbarthoこの回答に感謝します。 ヘッダー情報にアクセスできれば素晴らしい機能です。 私はjson-serverを使用しています。これは、カーソルベースのページ付け情報についても、ページ付け情報をHeaders
に配置します。
ちなみに、あなたのドキュメントには、 responseTansformer
とcustomFetch
オプションがあることがわかりました。 改ページ情報を取得するために彼らと何かをすることはできますか? 実際、私はたくさん試しましたが、それでも成功しませんでした...:
https://www.apollographql.com/docs/link/links/rest/#response -transforming
https://www.apollographql.com/docs/link/links/rest/#custom -fetch
残念ながら、 apollo-link-rest
はapollo-link
のAPIに依存してGraphQLにプラグインしますが、これは、JS Headers
APIを直接共有する明確な方法がないと思うことを意味します-しかし、それの非正規化バージョンが可能かもしれません。
そうは言っても、 responseTransformer
またはcustomFetch
オプションを使用して、必要なものにパッチを適用することができます。
responseTransformer
は、 response.headers
属性を持つJS Response
オブジェクトを受け取ります。
したがって、次のように書くことができます。
responseTransformer: async (resp: Response) => {
const body = await resp.json();
const interestingHeaders = {};
interestingHeaders.headerOne = resp.headers.get("headerOne"); // Pluck out the headers you want
body.__headers = interestingHeaders
return body;
}
ブラウザのバージョンによっては、 headers.entries()
を使用して、すべてのヘッダーをheaders.get()
ではなく1つのオブジェクトとして取得できる場合がありますが、現在Safari-iOSでは使用できません。
これは明らかに単純化されており、エラー処理はあなたに任されていますが、これはうまくいくと思います!
customFetch
でも可能ですが、 responseTransformer
が簡単だと思います。
@fbarthoうわー、これはかっこいい! 私はあなたのコードを試しました、それは動作し、私はリンクを取得しました。
ここで別の問題が発生します。クエリでbody.__headers.link
にアクセスするにはどうすればよいですか?
私のクエリコードは次のとおりです。
const queryTodos = gql`
query Todos($page: number, $limit: number) {
todos(_page: $page, _limit: $limit)
@rest(type: "TodoPagination", path: "/todos/?{args}") {
__headers {
link
}
userId
id
title
completed
}
}
`;
しかし、 __headers
がnullであるもの...
コードはここにあります:私はあなたのコードをClient.ts
に追加し、クエリコードはTodo.tsx
ます:
https://codesandbox.io/s/how-to-access-response-0mqx7?file=/src/Todos.tsx
@fbarthoこんにちは、私は3つの異なる方法を試しましたが、ついにこの問題を解決しました。 しかし、それが良い解決策であるかどうかはまだ疑問です。 ご意見をお聞かせください。
方法1:失敗しました。
最初は、 useQuery()
の__headers
をクエリでき、複数回試行しましたが、失敗したと思います。
方法2:解決策が疑わしいため、試しませんでした
responseTransformer
の応答の構造を変更し、 __headers
を__headers
キーに入れ、todoリストをtodo
キーに入れます。 しかし、それは良い解決策ではないと思います。 なぜなら、応答のすべての構造が変更されるからです。 したがって、 useQuery()
すべての構造を書き直す必要があります。
方法3:成功と完全な単純
__headers
をリアクティブ変数に入れました。 responseTransformer
関数では、 __headers
の値をリアクティブ変数に入れ、 useQuery()
実行された後にクエリを実行します。 ただし、クエリごとに異なるリアクティブ変数を作成する必要があるため、まだわかりません...
@blatoo 、これは古い問題で、私自身が遭遇したばかりで、 new ApolloLink
で解決しました
const paginationLink = new ApolloLink((operation, forward) => {
return forward(operation).map((response) => {
const context = operation.getContext();
const { headers } = context.restResponses[0] || null;
// in my case i'm making a bunch of sub queries, so i'm using `[0]` to get the headers from the top level.
if (headers) {
const pagination = getPaginationFromHeaders(headers.get('link'));
return { ...response, data: { ...response.data, pagination } };
}
return response;
});
});
const client = new ApolloClient({
cache: new InMemoryCache(),
link: concat(paginationLink, restLink),
});