Skip to content

Commit

Permalink
Update docs/data-fetching.md
Browse files Browse the repository at this point in the history
  • Loading branch information
koistya committed Apr 25, 2017
1 parent 6c1b54c commit 6b03906
Showing 1 changed file with 53 additions and 23 deletions.
76 changes: 53 additions & 23 deletions docs/data-fetching.md
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

0 comments on commit 6b03906

Please sign in to comment.