|
| 1 | +--- |
| 2 | +layout: default |
| 3 | +title: "fetchJson" |
| 4 | +--- |
| 5 | + |
| 6 | +# `fetchJson` |
| 7 | + |
| 8 | +React-admin includes a `fetchJson` utility function to make HTTP calls. It's a wrapper around the browser's `fetch` function, that adds the following features: |
| 9 | + |
| 10 | +- It adds the `Content-Type='application/json'` header to all non GET requests |
| 11 | +- It adds the `Authorization` header with optional parameters |
| 12 | +- It makes it easier to add custom headers to all requests |
| 13 | +- It handles the JSON decoding of the response |
| 14 | +- It handles HTTP errors codes by throwing an `HttpError` |
| 15 | + |
| 16 | +## Usage |
| 17 | + |
| 18 | +You can use it to make HTTP calls directly, to build a custom [`dataProvider`](./DataProviderIntroduction.md), or pass it directly to any `dataProvider` that supports it, such as [`ra-data-simple-rest`](https://github.com/marmelab/react-admin/tree/master/packages/ra-data-simple-rest). |
| 19 | + |
| 20 | +```jsx |
| 21 | +import { fetchUtils, Admin, Resource } from 'react-admin'; |
| 22 | +import simpleRestProvider from 'ra-data-simple-rest'; |
| 23 | +import { PostList } from './posts'; |
| 24 | + |
| 25 | +const httpClient = async (url, options = {}) => { |
| 26 | + const { status, headers, body, json } = fetchUtils.fetchJson(url, options); |
| 27 | + console.log('fetchJson result', { status, headers, body, json }); |
| 28 | + return { status, headers, body, json }; |
| 29 | +} |
| 30 | +const dataProvider = simpleRestProvider('http://path.to.my.api/', httpClient); |
| 31 | + |
| 32 | +const App = () => ( |
| 33 | + <Admin dataProvider={dataProvider}> |
| 34 | + <Resource name="posts" list={PostList} /> |
| 35 | + </Admin> |
| 36 | +); |
| 37 | +``` |
| 38 | + |
| 39 | +**Tip:** `fetchJson` is included in the `fetchUtils` object exported by the `react-admin` package. |
| 40 | + |
| 41 | +## Parameters |
| 42 | + |
| 43 | +`fetchJson(url, options)` expects the following parameters: |
| 44 | + |
| 45 | +- `url` **string** The URL to fetch |
| 46 | +- `options` **Object** The options to pass to the fetch call. Defaults to `{}`. |
| 47 | +- `options.user` **Object** The user object, used for the `Authorization` header |
| 48 | +- `options.user.token` **string** The token to pass as the `Authorization` header |
| 49 | +- `options.user.authenticated` **boolean** Whether the user is authenticated or not (the `Authorization` header will be set only if this is true) |
| 50 | +- `options.headers` **Headers** The headers to pass to the fetch call |
| 51 | + |
| 52 | +## Return Value |
| 53 | + |
| 54 | +`fetchJson` returns an object with the following properties: |
| 55 | + |
| 56 | +- `status` **number** The HTTP status code |
| 57 | +- `headers` **Headers** The response headers |
| 58 | +- `body` **string** The response body |
| 59 | +- `json` **Object** The response body, parsed as JSON |
| 60 | + |
| 61 | +## Adding Custom Headers |
| 62 | + |
| 63 | +Here is an example of how to add custom headers to all requests: |
| 64 | + |
| 65 | +```jsx |
| 66 | +import { fetchUtils, Admin, Resource } from 'react-admin'; |
| 67 | +import simpleRestProvider from 'ra-data-simple-rest'; |
| 68 | +import { PostList } from './posts'; |
| 69 | + |
| 70 | +const httpClient = (url, options = {}) => { |
| 71 | + if (!options.headers) { |
| 72 | + options.headers = new Headers({ Accept: 'application/json' }); |
| 73 | + } |
| 74 | + // add your own headers here |
| 75 | + options.headers.set('X-Custom-Header', 'foobar'); |
| 76 | + return fetchUtils.fetchJson(url, options); |
| 77 | +} |
| 78 | +const dataProvider = simpleRestProvider('http://path.to.my.api/', httpClient); |
| 79 | + |
| 80 | +const App = () => ( |
| 81 | + <Admin dataProvider={dataProvider}> |
| 82 | + <Resource name="posts" list={PostList} /> |
| 83 | + </Admin> |
| 84 | +); |
| 85 | +``` |
| 86 | + |
| 87 | +## TypeScript Support |
| 88 | + |
| 89 | +For TypeScript users, here is a typed example of a custom `httpClient` that adds custom headers to all requests: |
| 90 | + |
| 91 | +```ts |
| 92 | +import { fetchUtils } from 'react-admin'; |
| 93 | + |
| 94 | +const httpClient = (url: string, options: fetchUtils.Options = {}) => { |
| 95 | + const customHeaders = (options.headers || |
| 96 | + new Headers({ |
| 97 | + Accept: 'application/json', |
| 98 | + })) as Headers; |
| 99 | + // add your own headers here |
| 100 | + customHeaders.set('X-Custom-Header', 'foobar'); |
| 101 | + options.headers = customHeaders; |
| 102 | + return fetchUtils.fetchJson(url, options); |
| 103 | +} |
| 104 | +``` |
| 105 | + |
| 106 | +## Adding The `Authorization` Header |
| 107 | + |
| 108 | +Here is an example of how to add the `Authorization` header to all requests, using a token stored in the browser's local storage: |
| 109 | + |
| 110 | +```jsx |
| 111 | +import { fetchUtils } from 'react-admin'; |
| 112 | + |
| 113 | +const httpClient = (url, options = {}) => { |
| 114 | + const token = localStorage.getItem('token'); |
| 115 | + const user = { token: `Bearer ${token}`, authenticated: !!token }; |
| 116 | + return fetchUtils.fetchJson(url, {...options, user}); |
| 117 | +} |
| 118 | +``` |
| 119 | + |
| 120 | +**Tip:** The `Authorization` header will only be added to the request if `user.authenticated` is `true`. |
| 121 | + |
| 122 | +## Handling HTTP Errors |
| 123 | + |
| 124 | +The `fetchJson` function rejects with an `HttpError` when the HTTP response status code is not in the 2xx range. |
| 125 | + |
| 126 | +```jsx |
| 127 | +import { fetchUtils } from 'react-admin'; |
| 128 | + |
| 129 | +fetchUtils.fetchJson('https://jsonplaceholder.typicode.com/posts/1') |
| 130 | + .then(({ json }) => console.log('HTTP call succeeded. Return value:', json)) |
| 131 | + .catch(error => console.log('HTTP call failed. Error message:', error)); |
| 132 | +``` |
0 commit comments