Skip to content

Commit 0703076

Browse files
feat: HTTP GET Support (#410)
* fix: remove .size-snapshot.json * test: client.useGETForQueries & fetchOptionsOverrides.method=GET * feat: GET support * fix: update types * fix: update fastify-ssr example, use GET for manualQuery example * doc: update docs RE GET support Co-authored-by: Guillermo Gonzalez <[email protected]>
1 parent b99ad03 commit 0703076

File tree

10 files changed

+276
-188
lines changed

10 files changed

+276
-188
lines changed

Diff for: .gitignore

+2-1
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,5 @@ dist
88
es
99
packages/graphql-hooks/README.md
1010
packages/*/LICENSE
11-
build
11+
build
12+
.size-snapshot.json

Diff for: README.md

+41-8
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ function MyComponent() {
102102
- [SSR](#SSR)
103103
- [Pagination](#Pagination)
104104
- [File uploads](#File-uploads)
105+
- [HTTP Get Support](#HTTP-Get-support)
105106
- [Authentication](#Authentication)
106107
- [Fragments](#Fragments)
107108
- [Migrating from Apollo](#Migrating-from-Apollo)
@@ -127,6 +128,7 @@ const client = new GraphQLClient(config)
127128

128129
- `url` (**Required**): The url to your GraphQL server
129130
- `ssrMode`: Boolean - set to `true` when using on the server for server-side rendering; defaults to `false`
131+
- `useGETForQueries`: Boolean - set to `true` to use HTTP GET method for all queries; defaults to false. See [HTTP Get Support](#HTTP-Get-support) for more info
130132
- `cache` (**Required** if `ssrMode` is `true`, otherwise optional): Object with the following methods:
131133
- `cache.get(key)`
132134
- `cache.set(key, data)`
@@ -231,9 +233,9 @@ const { loading, error, data, refetch, cacheHit } = useQuery(QUERY)
231233
- `options`: Object - options that will be merged into the `options` that were passed into `useQuery` (see above).
232234
- `cacheHit`: Boolean - `true` if the query result came from the cache, useful for debugging
233235
- `error`: Object - Set if at least one of the following errors has occured and contains:
234-
* `fetchError`: Object - Set if an error occurred during the `fetch` call
235-
* `httpError`: Object - Set if an error response was returned from the server
236-
* `graphQLErrors`: Array - Populated if any errors occurred whilst resolving the query
236+
- `fetchError`: Object - Set if an error occurred during the `fetch` call
237+
- `httpError`: Object - Set if an error response was returned from the server
238+
- `graphQLErrors`: Array - Populated if any errors occurred whilst resolving the query
237239

238240
## `useManualQuery`
239241

@@ -508,6 +510,34 @@ export default function PostForm() {
508510
}
509511
```
510512

513+
## HTTP Get support
514+
515+
Using `GET` for queries can be useful, especially when implementing any sort of HTTP caching strategy. There are two ways you can do this:
516+
517+
**Per Query**
518+
519+
```js
520+
const { loading, error, data } = useQuery(MY_QUERY, {
521+
fetchOptionsOverrides: { method: 'GET' }
522+
})
523+
524+
// same goes for useManualQuery
525+
const [fetchSomething] = useManualQuery(MY_QUERY, {
526+
fetchOptionsOverrides: { method: 'GET' }
527+
})
528+
```
529+
530+
**For All Queries**
531+
532+
When you create your client, set the `useGETForQueries` option as `true`:
533+
534+
```js
535+
const client = new GraphQLClient({
536+
url: '/graphql',
537+
useGETForQueries: true
538+
})
539+
```
540+
511541
## Authentication
512542

513543
Coming soon!
@@ -706,11 +736,14 @@ import { buildAxiosFetch } from '@lifeomic/axios-fetch'
706736
import { GraphQLClient } from 'graphql-hooks'
707737

708738
const gqlAxios = axios.create()
709-
gqlAxios.interceptors.response.use(function (response) {
710-
return response
711-
}, function (error) {
712-
// Handle expired JWT and refresh token
713-
})
739+
gqlAxios.interceptors.response.use(
740+
function(response) {
741+
return response
742+
},
743+
function(error) {
744+
// Handle expired JWT and refresh token
745+
}
746+
)
714747

715748
const client = new GraphQLClient({
716749
url: '/graphql',

Diff for: examples/fastify-ssr/src/app/pages/HomePage.js

+9-2
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,12 @@ function HomePage() {
3737
const [createUser] = useMutation(CREATE_USER_MUTATION)
3838

3939
const [getFirstUser, { data: firstUserData }] = useManualQuery(
40-
GET_FIRST_USER_QUERY
40+
GET_FIRST_USER_QUERY,
41+
{
42+
fetchOptionsOverrides: {
43+
method: 'GET'
44+
}
45+
}
4146
)
4247

4348
async function createNewUser() {
@@ -73,7 +78,9 @@ function HomePage() {
7378
/>
7479
<button onClick={createNewUser}>Create User</button>
7580
</div>
76-
<button onClick={getFirstUser}>Manually trigger Query</button>
81+
<button onClick={getFirstUser}>
82+
Manually trigger Query via GET method
83+
</button>
7784
<div>First User: {firstUserData && firstUserData.firstUser.name}</div>
7885
</div>
7986
)

Diff for: packages/graphql-hooks-memcache/.size-snapshot.json

-88
This file was deleted.

Diff for: packages/graphql-hooks/.size-snapshot.json

-88
This file was deleted.

Diff for: packages/graphql-hooks/index.d.ts

+1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ export class GraphQLClient {
1010
ssrMode: boolean
1111
fetchOptions: object
1212
logErrors: boolean
13+
useGETForQueries: boolean
1314

1415
private onError(): any
1516
private fetch(): Promise<any>

Diff for: packages/graphql-hooks/src/GraphQLClient.js

+26-1
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ class GraphQLClient {
3030
this.fetchOptions = config.fetchOptions || {}
3131
this.logErrors = config.logErrors !== undefined ? config.logErrors : true
3232
this.onError = config.onError
33+
this.useGETForQueries = config.useGETForQueries === true
3334
}
3435

3536
setHeader(key, value) {
@@ -129,6 +130,10 @@ class GraphQLClient {
129130
...fetchOptionsOverrides
130131
}
131132

133+
if (fetchOptions.method === 'GET') {
134+
return fetchOptions
135+
}
136+
132137
const { clone, files } = extractFiles(operation)
133138
const operationJSON = JSON.stringify(clone)
134139

@@ -162,8 +167,28 @@ class GraphQLClient {
162167
}
163168

164169
request(operation, options = {}) {
170+
let url = this.url
171+
const fetchOptions = this.getFetchOptions(
172+
operation,
173+
options.fetchOptionsOverrides
174+
)
175+
176+
if (fetchOptions.method === 'GET') {
177+
const paramsQueryString = Object.entries(operation)
178+
.filter(([, v]) => !!v)
179+
.map(([k, v]) => {
180+
if (k === 'variables') {
181+
v = JSON.stringify(v)
182+
}
183+
184+
return `${k}=${encodeURIComponent(v)}`
185+
})
186+
.join('&')
187+
url = url + '?' + paramsQueryString
188+
}
189+
165190
return this.fetch(
166-
this.url,
191+
url,
167192
this.getFetchOptions(operation, options.fetchOptionsOverrides)
168193
)
169194
.then(response => {

Diff for: packages/graphql-hooks/src/useClientRequest.js

+7
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,13 @@ function useClientRequest(query, initialOpts = {}) {
8181
operationName: initialOpts.operationName
8282
}
8383

84+
if (client.useGETForQueries && !initialOpts.isMutation) {
85+
initialOpts.fetchOptionsOverrides = {
86+
...initialOpts.fetchOptionsOverrides,
87+
method: 'GET'
88+
}
89+
}
90+
8491
const cacheKey = client.getCacheKey(operation, initialOpts)
8592
const isDeferred = initialOpts.isMutation || initialOpts.isManual
8693
const initialCacheHit =

0 commit comments

Comments
 (0)