-
-
Notifications
You must be signed in to change notification settings - Fork 4.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
1 changed file
with
53 additions
and
23 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,30 +1,60 @@ | ||
## Data Fetching with WHATWG Fetch | ||
|
||
There is isomorphic `core/fetch` module that can be used the same way in both | ||
client-side and server-side code as follows: | ||
|
||
```jsx | ||
export const path = '/products'; | ||
export const action = async ({ fetch }) => { | ||
const response = await fetch('/graphql?query={products{id,name}}'); | ||
const data = await response.json(); | ||
return <Layout><Products {...data} /></Layout>; | ||
}; | ||
## Data Fetching | ||
|
||
At a bare minimum you may want to use [HTML5 Fetch API][fetch] as an HTTP client utility for | ||
making Ajax request to the [data API server][nodeapi]. This API is supported natively in all the | ||
major browsers except for IE (note, that Edge browser does support Fetch). | ||
|
||
**React Starter Kit** is pre-configured with [`whatwg-fetch`][wfetch] polyfill for the browser | ||
environment and [`node-fetch`][nfetch] module for the server-side environment (see | ||
[`src/createFetch.js`](../src/createFetch.js)), allowing you to use the `fetch(url, options)` | ||
method universally in both the client-side and server-side code bases. | ||
|
||
In order to avoid the the amount of boilerplate code needed when using the raw `fetch(..)` | ||
function, a simple wrapper was created that provides a base URL of the data API server, credentials | ||
(cookies), CORS etc. For example, in a browser environment the base URL of the data API server | ||
might be an empty string, so when you make an Ajax request to the `/graphql` endpoint it's being | ||
sent to the same origin, and when the same code is executed on the server, during server-side | ||
rendering, it fetches data from the `http://api:8080/graphql` endpoint (`node-fetch` doesn't | ||
support relative URLs for obvious reasons). | ||
|
||
Because of these subtle differences of how the `fetch` method works internally, it makes total | ||
sense to pass it as a `context` variable to your React application, so it can be used from either | ||
routing level or from inside your React components as follows: | ||
|
||
#### Route Example | ||
|
||
```js | ||
{ | ||
path: '/posts/:id', | ||
async action({ params, fetch }) { | ||
const resp = await fetch(`/api/posts/${params.id}`, { method: 'GET' }); | ||
const data = await resp.json(); | ||
return { title: data.title, component: <Post {...data} /> }; | ||
} | ||
} | ||
``` | ||
|
||
When this code executes on the client, the Ajax request will be sent via | ||
GitHub's [fetch](https://github.com/github/fetch) library (`whatwg-fetch`), | ||
that itself uses XHMLHttpRequest behind the scene unless `fetch` is supported | ||
natively by the user's browser. | ||
#### React Component | ||
|
||
```js | ||
class Post extends React.Component { | ||
static context = { fetch: PropTypes.func.isRequired }; | ||
handleDelete = (event) => { | ||
event.preventDefault(); | ||
const id = event.target.dataset['id']; | ||
this.context.fetch(`/api/posts/${id}`, { method: 'DELETE' }).then(...); | ||
}; | ||
render() { ... } | ||
} | ||
``` | ||
|
||
Whenever the same code executes on the server, it uses | ||
[node-fetch](https://github.com/bitinn/node-fetch) module behind the scene that | ||
itself sends an HTTP request via Node.js `http` module. It also converts | ||
relative URLs to absolute (see `./core/fetch/fetch.server.js`). | ||
#### Related articles | ||
|
||
Both `whatwg-fetch` and `node-fetch` modules have almost identical API. If | ||
you're new to this API, the following article may give you a good introduction: | ||
* https://jakearchibald.com/2015/thats-so-fetch/ | ||
|
||
https://jakearchibald.com/2015/thats-so-fetch/ | ||
|
||
[fetch]: https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch | ||
[wfetch]: https://github.com/github/fetchno | ||
[nfetch]: https://github.com/bitinn/node-fetch | ||
[nodeapi]: https://github.com/kriasoft/nodejs-api-starter | ||
|