-
-
Notifications
You must be signed in to change notification settings - Fork 4.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Initialize a new HTTP client for each web request #1237
Merged
Merged
Changes from all commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
487f19b
Initialize a new HTTP client for each web request
koistya 0b1e1e4
Fix ESLint warning in Html.js
koistya 6c1b54c
Make createFetch more readable
koistya e0222a3
Update docs/data-fetching.md
koistya 19b555e
Code style fixes
koistya 0dcd16e
Code style fixes
koistya File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
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,32 +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 | ||
import fetch from '../core/fetch'; | ||
|
||
export const path = '/products'; | ||
export const action = async () => { | ||
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: | ||
* [That's so fetch!](https://jakearchibald.com/2015/thats-so-fetch/) by [Jake Archibald](https://twitter.com/jaffathecake) | ||
|
||
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 | ||
|
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
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
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
File renamed without changes.
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
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
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
add
credentials: 'same-origin'
here?