├── .babelrc
├── .eslintrc
├── .gitignore
├── .npmrc
├── .prettierignore
├── .prettierrc
├── .travis.yml
├── CHANGELOG.md
├── LICENSE
├── README.md
├── ROADMAP.md
├── docs
├── FAQ.md
├── examples.md
└── guides
│ ├── INDEX.md
│ ├── aborting.md
│ ├── best-practices.md
│ ├── differences-with-apollo.md
│ ├── differences-with-fetch.md
│ ├── integration-with-other-technologies.md
│ ├── request-deduplication.md
│ ├── request-keys.md
│ ├── response-caching.md
│ └── using-the-lazy-prop.md
├── examples
├── fetch-components
│ ├── .gitignore
│ ├── README.md
│ ├── package.json
│ ├── public
│ │ ├── favicon.ico
│ │ ├── index.html
│ │ └── manifest.json
│ └── src
│ │ ├── App.js
│ │ ├── fetch-components
│ │ └── posts.js
│ │ └── index.js
├── lazy-read
│ ├── .gitignore
│ ├── README.md
│ ├── package.json
│ ├── public
│ │ ├── favicon.ico
│ │ ├── index.html
│ │ └── manifest.json
│ └── src
│ │ ├── App.js
│ │ └── index.js
├── multiple-requests
│ ├── .gitignore
│ ├── README.md
│ ├── package.json
│ ├── public
│ │ ├── favicon.ico
│ │ ├── index.html
│ │ └── manifest.json
│ └── src
│ │ ├── App.js
│ │ └── index.js
├── request-deduplication
│ ├── .gitignore
│ ├── README.md
│ ├── package.json
│ ├── public
│ │ ├── favicon.ico
│ │ ├── index.html
│ │ └── manifest.json
│ └── src
│ │ ├── App.js
│ │ └── index.js
├── response-caching
│ ├── .gitignore
│ ├── README.md
│ ├── package.json
│ ├── public
│ │ ├── favicon.ico
│ │ ├── index.html
│ │ └── manifest.json
│ └── src
│ │ ├── App.js
│ │ └── index.js
├── simple-read
│ ├── .gitignore
│ ├── README.md
│ ├── package.json
│ ├── public
│ │ ├── favicon.ico
│ │ ├── index.html
│ │ └── manifest.json
│ └── src
│ │ ├── App.js
│ │ └── index.js
└── updating-a-resource
│ ├── .gitignore
│ ├── README.md
│ ├── package.json
│ ├── public
│ ├── favicon.ico
│ ├── index.html
│ └── manifest.json
│ └── src
│ ├── App.js
│ └── index.js
├── jest.config.js
├── package.json
├── rollup.config.js
├── src
├── fetch.js
└── index.js
└── test
├── .eslintrc
├── do-fetch.test.js
├── index.test.js
├── responses.js
├── same-component.test.js
└── setup.js
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "env": {
3 | "build": {
4 | "presets": [
5 | ["env", {
6 | "modules": false
7 | }], "stage-3", "react"
8 | ],
9 | "plugins": ["external-helpers", "transform-class-properties"]
10 | },
11 | "buildProd": {
12 | "presets": [
13 | ["env", {
14 | "modules": false
15 | }], "stage-3", "react"
16 | ],
17 | "plugins": [
18 | "external-helpers",
19 | "transform-class-properties", [
20 | "transform-react-remove-prop-types",
21 | {
22 | "mode": "remove",
23 | "removeImport": true
24 | }
25 | ]
26 | ]
27 | },
28 | "es": {
29 | "presets": [
30 | ["env", {
31 | "modules": false
32 | }], "stage-3", "react"
33 | ],
34 | "plugins": ["transform-class-properties"]
35 | },
36 | "commonjs": {
37 | "plugins": [
38 | ["transform-es2015-modules-commonjs", {
39 | "loose": true
40 | }],
41 | "transform-class-properties"
42 | ],
43 | "presets": ["stage-3", "react"]
44 | },
45 | "test": {
46 | "presets": ["env", "stage-3", "react"],
47 | "plugins": ["transform-class-properties"]
48 | }
49 | }
50 | }
--------------------------------------------------------------------------------
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "parser": "babel-eslint",
3 | "extends": "eslint:recommended",
4 | "parserOptions": {
5 | "ecmaVersion": 8,
6 | "sourceType": "module",
7 | "ecmaFeatures": {
8 | "experimentalObjectRestSpread": true
9 | }
10 | },
11 | "rules": {
12 | "no-unused-vars": "error",
13 | "no-use-before-define": "error",
14 | "react/jsx-uses-react": "error",
15 | "react/jsx-uses-vars": "error"
16 | },
17 | "env": {
18 | "browser": true,
19 | "node": true
20 | },
21 | "globals": {
22 | "Promise": true
23 | },
24 | "plugins": ["react"]
25 | }
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 |
6 | # testing
7 | /coverage
8 |
9 | # production
10 | /build
11 |
12 | # misc
13 | .DS_Store
14 | .env.local
15 | .env.development.local
16 | .env.test.local
17 | .env.production.local
18 |
19 | .vscode
20 |
21 | npm-debug.log*
22 | yarn-debug.log*
23 | yarn-error.log*
24 |
25 | package-lock.json
26 | package-lock.json.*
27 | dist
28 | es
29 | lib
--------------------------------------------------------------------------------
/.npmrc:
--------------------------------------------------------------------------------
1 | package-lock=false
--------------------------------------------------------------------------------
/.prettierignore:
--------------------------------------------------------------------------------
1 | package.json
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "singleQuote": true,
3 | "jsxBracketSameLine": true,
4 | "trailingComma": "all"
5 | }
6 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | node_js:
3 | - "8"
4 | sudo: false
5 | notifications:
6 | email: false
7 | after_success:
8 | # Upload to coveralls, but don't _fail_ if coveralls is down.
9 | - cat coverage/lcov.info | node_modules/.bin/coveralls || echo "Coveralls upload failed"
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | ### v3.2.0 (2021/1/11)
4 |
5 | - React 17 is now included in peer dependencies.
6 |
7 | ### v3.1.2 (2018/8/2)
8 |
9 | **Bug Fixes**
10 |
11 | - Fixes a bug that can occur in React Native environments
12 |
13 | ### v3.1.1 (2018/7/10)
14 |
15 | **Bug Fixes**
16 |
17 | - A race condition has been fixed.
18 |
19 | ### v3.1.0 (2018/7/10)
20 |
21 | **New Features**
22 |
23 | - `doFetch` now returns a Promise that _always_ resolves. The value that it resolves to is
24 | the same object that is passed to `afterFetch`. Note that `afterFetch` is only called when a
25 | network request has actually been performed, whereas `doFetch` resolves even when the cache is hit.
26 |
27 | ### v3.0.1 (2018/4/24)
28 |
29 | **Bug Fixes**
30 |
31 | - Fixes a bug where `isLazy` would sometimes be computed using previous
32 | props rather than the current props.
33 |
34 | ### v3.0.0 (2018/4/24)
35 |
36 | > Although the changes in this release are technically breaking, they are unlikely to
37 | > affect most users' code.
38 |
39 | **Breaking Changes**
40 |
41 | - When a request fails, the `data` from a request will no longer be set to `null`. This
42 | allows you to control whether or not your UI continues to display the existing data.
43 |
44 | - The `responseType` prop is now more forgiving. If the body cannot be parsed with
45 | the `responseType` that you set, then `data` will be set to `null`.
46 |
47 | ### v2.0.4 (2018/4/20)
48 |
49 | **Bug Fixes**
50 |
51 | - Fixes a bug where there could be a cache mismatch when re-rendering the same component
52 | that has a fetch policy configured.
53 |
54 | ### v2.0.3 (2018/3/2)
55 |
56 | **Bug Fixes**
57 |
58 | - Fixes a bug where the `lazy` prop was not always respected. Anytime that a new request key was generated,
59 | a request would be made.
60 |
61 | ### v2.0.2 (2018/2/21)
62 |
63 | **Bug Fixes**
64 |
65 | - Fixes a bug where an Uncaught ReferenceError could be thrown
66 |
67 | ### v2.0.1 (2018/2/17)
68 |
69 | **Bug Fixes**
70 |
71 | - This fixes a problem where the default `fetchPolicy` would be `"cache-first"` for "write" requests.
72 |
73 | ### v2.0.0 (2018/2/17)
74 |
75 | **Breaking**
76 |
77 | - `transformResponse` has been renamed to be `transformData`
78 | - `fetchPolicy` is now determined by the method that you pass in. This change was made to support using
79 | POST methods for read requests, and is unlikely to break your code.
80 | - A new prop, `cacheResponse`, is used to determine if a response is added to the cache or
81 | not. This is to support using POST methods for read requests, and is unlikely to break your code.
82 |
83 | **New Features**
84 |
85 | - A new `failed` property is passed to you in the render prop callback. This allows you to
86 | quickly determine if a request failed for any reason (be it network errors or "error" status
87 | codes).
88 |
89 | ### v1.1.0 (2018/2/7)
90 |
91 | **New Features**
92 |
93 | - `responseType` can now be specified as a function. It receives the `response`
94 | as the first argument.
95 | - Adds a `requestKey` prop.
96 | - When the request is "faux-aborted," the error will have a `name` equal to `AbortError`.
97 | This matches the name of the native error, allowing you to write future-proof code that
98 | handles aborted requests.
99 |
100 | ### v1.0.0 (2018/2/4)
101 |
102 | **Breaking**
103 |
104 | - The `responseType` will now be set to `"text"` anytime a response returns
105 | with a 204 status code.
106 | - The `responseType` is no longer used when creating the request key.
107 |
108 | ### v0.3.0 (2018/2/4)
109 |
110 | **Changes**
111 |
112 | - `fetch-dedupe` has been abstracted into a separate library. This
113 | does not change the public API of this library.
114 |
115 | ### v0.2.0 (2018/2/1)
116 |
117 | **New Features**
118 |
119 | - The render prop will now be passed the `requestKey`.
120 |
121 | ### v0.1.0 (2018/2/1)
122 |
123 | React's new Context API has been finalized, and it uses functional `children` rather than a prop
124 | named `render`. Accordingly, this library has been updated to use `children` as the default.
125 |
126 | **Breaking**
127 |
128 | - `` now uses `children` as the render prop, rather than `render`.
129 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 James, please
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # React Request
2 |
3 | [](https://travis-ci.org/jamesplease/react-request)
4 | [](https://www.npmjs.com/package/react-request)
5 | [](https://coveralls.io/github/jamesplease/react-request?branch=master)
6 | [](https://unpkg.com/react-request/dist/react-request.min.js)
7 |
8 | Declarative HTTP requests for React.
9 |
10 | ### Motivation
11 |
12 | Making a single HTTP request is not difficult to do in JavaScript. However,
13 | complex web applications often make many requests as the
14 | user navigates through the app.
15 |
16 | Features such as request deduplication and response caching can often save the
17 | developer of apps like these from headache and bugs. Although it is possible to
18 | implement these features imperatively, it requires that you write a bit of
19 | code, and that code can be tedious to test.
20 |
21 | A declarative API makes things a lot simpler for you, which is where React Request
22 | comes in. React Request is a backend-agnostic, declarative solution for HTTP
23 | requests in React, and its deduping and caching features are a delight to use.
24 |
25 | ### Features
26 |
27 | ✓ Uses the native [fetch](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) API
28 | ✓ Smart [deduping of requests](./docs/guides/request-deduplication.md)
29 | ✓ Customizable [response caching](./docs/guides/response-caching.md)
30 | ✓ Integrates with external stores (such as [Redux](https://github.com/reactjs/redux))
31 | ✓ Reasonable footprint (~2kb gzipped)
32 |
33 | ### Installation
34 |
35 | Install using [npm](https://www.npmjs.com):
36 |
37 | ```
38 | npm install react-request
39 | ```
40 |
41 | or [yarn](https://yarnpkg.com/):
42 |
43 | ```
44 | yarn add react-request
45 | ```
46 |
47 | ### Documentation
48 |
49 | - [**Getting Started**](#getting-started)
50 | - [**API**](#api)
51 | - [\](#fetch-)
52 | - [props](#props)
53 | - [Arguments passed to the render prop](#propschildren)
54 | - [Using `doFetch`](#using-dofetch)
55 | - [fetchDedupe()](#fetchdedupe-input--init--dedupeoptions-)
56 | - [getRequestKey()](#getrequestkey-url-method-body-responsetype-)
57 | - [isRequestInFlight()](#isrequestinflight-requestkey-)
58 | - [clearRequestCache()](#clearrequestcache)
59 | - [clearResponseCache()](#clearresponsecache)
60 | - [**Guides ⇗**](./docs/guides/INDEX.md)
61 | - [Response Caching ⇗](./docs/guides/response-caching.md)
62 | - [Request Deduplication ⇗](./docs/guides/request-deduplication.md)
63 | - [Request Keys ⇗](./docs/guides/request-keys.md)
64 | - [Best Practices ⇗](./docs/guides/best-practices.md)
65 | - [Using the `lazy` Prop ⇗](./docs/guides/using-the-lazy-prop.md)
66 | - [Aborting ⇗](./docs/guides/aborting.md)
67 | - [Differences with `fetch()` ⇗](./docs/guides/differences-with-fetch.md)
68 | - [Differences with React Apollo ⇗](./docs/guides/differences-with-apollo.md)
69 | - [Integration with Other Technologies ⇗](./docs/guides/integration-with-other-technologies.md)
70 | - [**Examples ⇗**](./docs/examples.md)
71 | - [**FAQ ⇗**](./docs/FAQ.md)
72 | - [**Roadmap ⇗**](./ROADMAP.md)
73 | - [**Acknowledgements**](#acknowledgements)
74 |
75 | ### Getting Started
76 |
77 | Here's a quick look at what using React Request is like:
78 |
79 | ```jsx
80 | import React, { Component } from 'react';
81 | import { Fetch } from 'react-request';
82 |
83 | class App extends Component {
84 | render() {
85 | return (
86 |
87 | {({ fetching, failed, data }) => {
88 | if (fetching) {
89 | return
Loading data...
;
90 | }
91 |
92 | if (failed) {
93 | return
The request did not succeed.
;
94 | }
95 |
96 | if (data) {
97 | return (
98 |
99 |
Post ID: {data.id}
100 |
Post Title: {data.title}
101 |
102 | );
103 | }
104 |
105 | return null;
106 | }}
107 |
108 | );
109 | }
110 | }
111 | ```
112 |
113 | Need to make multiple requests? You can use any tool that you would like that
114 | allows you to "compose" [render prop components](https://reactjs.org/docs/render-props.html) together. This example
115 | uses [React Composer](https://github.com/jamesplease/react-composer):
116 |
117 | ```jsx
118 | import React, { Component } from 'react';
119 | import Composer from 'react-composer';
120 |
121 | class App extends Component {
122 | render() {
123 | return (
124 | ,
127 | ,
131 | ]}>
132 | {([readPost, deletePost]) => {
133 | return (
134 |
135 | {readPost.fetching && 'Loading post 1'}
136 | {!readPost.fetching && 'Post 1 is not being fetched'}
137 |
140 |
141 | );
142 | }}
143 |
144 | );
145 | }
146 | }
147 | ```
148 |
149 | These examples just scratch the surface of what React Request can do for you.
150 | Check out the API reference below, or
151 | [read the guides](https://github.com/jamesplease/react-request/blob/master/docs/guides/INDEX.md),
152 | to learn more.
153 |
154 | ### API
155 |
156 | #### ``
157 |
158 | A component for making a single HTTP request. This is the export from this library that you will use
159 | most frequently.
160 |
161 | ```jsx
162 | import { Fetch } from 'react-request';
163 | ```
164 |
165 | ##### Props
166 |
167 | The `` components accepts every value of `init` and `input`
168 | from the
169 | [`fetch()`](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch)
170 | API as a prop, in addition to a few other things.
171 |
172 | The complete list of props is:
173 |
174 | | Prop | Default value | Description |
175 | | ------------------------------------ | ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
176 | | url | | From [`fetch()`](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch). The URL to send the request to |
177 | | method | `'GET'` | From [`fetch()`](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch). The HTTP method to use |
178 | | body | | From [`fetch()`](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch). The request body to send along with the request |
179 | | credentials | | From [`fetch()`](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch). The request credentials you want to use for the request: `omit`, `same-origin`, or `include.` |
180 | | headers | | From [`fetch()`](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch). Headers to send along with the request |
181 | | [children](#propschildren) | | A function that is called with a single argument containing information about the request. Learn more. |
182 | | [lazy](#propslazy) | _Varies_ | Whether or not the request is made when the component mounts. |
183 | | [beforeFetch](#propsbeforefetch) | | A function called before a network request is made. |
184 | | [afterFetch](#propsafterfetch) | | A function that is only called after a network request is made. |
185 | | [onResponse](#propsonresponse) | | A function called anytime a response is received, whether from the network or cache. |
186 | | [transformData](#propstransformdata) | | A function that is called with the body of the response, allowing you to transform it. |
187 | | [responseType](#propsresponsetype) | `'json'` | Whether or not the request is made when the component mounts. |
188 | | [requestName](#propsrequestname) | | A name to give this request, which can be useful for debugging. |
189 | | [fetchPolicy](#propsfetchpolicy) | | The cache strategy to use. |
190 | | [cacheResponse](#propscacheresponse) | _Varies_ | Whether or not to cache the response for this request. |
191 | | [dedupe](#propsdedupe) | `true` | Whether or not to dedupe this request. |
192 | | [requestKey](#propsrequestkey) | _Generated_ | A key that is used for deduplication and response caching. |
193 | | mode | | From [`fetch()`](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch). The mode you want to use for the request |
194 | | cache | | From [`fetch()`](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch). The browser's cache mode you want to use for the request |
195 | | redirect | | From [`fetch()`](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch). The redirect mode to use |
196 | | referrer | `'about:client'` | From [`fetch()`](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch). The referrer to use for the request |
197 | | referrerPolicy | `''` | From [`fetch()`](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch). Specifies the value of the referer HTTP header. |
198 | | integrity | `''` | From [`fetch()`](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch). Contains the [subresource integrity](https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity) value of the request |
199 | | keepalive | | From [`fetch()`](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch). Can be used to allow the request to outlive the page |
200 | | signal | | From [`fetch()`](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch). An AbortSignal object instance |
201 |
202 | To learn more about the valid options for the props that come from `fetch`, refer to the
203 | [`fetch()`](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch)
204 | documentation.
205 |
206 | The following example demonstrates some of the most commonly-used props that come from `fetch()`:
207 |
208 | ```jsx
209 |
217 | {({ doFetch }) => {
218 | ;
219 | }}
220 |
221 | ```
222 |
223 | In addition to the `fetch()` props, there are a number of other useful props.
224 |
225 | ##### `props.children`
226 |
227 | `children` is the [render prop](https://reactjs.org/docs/render-props.html) of this component.
228 | It is called with one argument, `result`, an object with the following keys:
229 |
230 | | Key | Type | Description |
231 | | ----------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
232 | | fetching | Boolean | A Boolean representing whether or not a request is currently in flight for this component |
233 | | failed | Boolean | A Boolean representing whether or not the request failed for any reason. This includes network errors and status codes that are greater than or equal to`400`. |
234 | | error | Object | An error object representing a network error occurred. Note that HTTP "error" status codes do not cause errors; only failed or aborted network requests do. For more, see the ["Using Fetch" MDN guide](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch#Checking_that_the_fetch_was_successful). |
235 | | response | Object | An instance of [Response](https://developer.mozilla.org/en-US/docs/Web/API/Response). The [`body`](https://developer.mozilla.org/en-US/docs/Web/API/Body) will already be read, and made available to you as `response.data`. |
236 | | data | Object | The data returned in `response`. This will be different from `response.data` if a `transformData` prop was passed to ``. |
237 | | doFetch | Function | A function that allows you to manually make the HTTP request. [Read more.](#using-dofetch) |
238 | | url | String | The URL that was passed as a prop to `` |
239 | | requestName | String | The name of the request (see `requestName` below) |
240 | | requestKey | String | The [request key](./docs/guides/request-keys.md) of the request |
241 |
242 | ###### Using doFetch
243 |
244 | There are three common use cases for the `doFetch` prop:
245 |
246 | - You can use it to "refresh" the data by making a follow-up request for read requests
247 | - You can use it to retry the request if there is any sort of error
248 | - You must manually call this method to actually make the request anytime that the `lazy` prop
249 | is passed as `true`.
250 |
251 | `doFetch` accepts one argument: `options`. Any of the `fetch()` options, such as `url`, `method`, and
252 | `body` are valid `options`. You may also specify a new `requestKey` if you are manually generating your
253 | own keys. This method allows you to customize the request from within the component based on the
254 | component's state.
255 |
256 | `doFetch` returns a Promise that **always** resolves. It resolves to the same argument that the
257 | [`afterFetch`](#afterFetch) prop receives.
258 |
259 | In the following example, we demonstrate how you can modify the request by passing options to `doFetch`.
260 |
261 | ```jsx
262 |
263 | {({ doFetch }) => (
264 | // You can pass options to `doFetch` to customize the request. All of the props from `fetch()`, such as `url`,
265 | // `body`, and so on, are supported.
266 |
269 | )}
270 |
271 | ```
272 |
273 | ##### `props.lazy`
274 |
275 | Whether or not the request will be called when the component mounts. The default value
276 | is based on the request method that you use.
277 |
278 | | Method | Default value |
279 | | ------------------------ | ------------- |
280 | | GET, HEAD, OPTIONS | `false` |
281 | | POST, PUT, PATCH, DELETE | `true` |
282 |
283 | ```jsx
284 |
285 | {({ doFetch }) => {
286 | ;
287 | }}
288 |
289 | ```
290 |
291 | ##### `props.beforeFetch`
292 |
293 | A function that is called just before a network request is initiated. It is called
294 | with one argument, an object with the following keys:
295 |
296 | - `url`: The URL of the request
297 | - `init`: The second argument passed to `global.fetch()`, which specifies things
298 | such as the body, method, and so on
299 | - `requestKey`: Either the computed request key, or the value of the
300 | `requestKey` prop
301 |
302 | This feature is useful for analytics, or syncing response data with a data store such
303 | as [Redux](https://github.com/reactjs/redux/).
304 |
305 | > Note: This function is not called when the component reads from the cache.
306 |
307 | ##### `props.afterFetch`
308 |
309 | A function that is called anytime that a network response is received. It is called
310 | with one argument, an object with the following keys:
311 |
312 | - `url`: The URL of the request
313 | - `init`: The second argument passed to `global.fetch()`, which specifies things
314 | such as the body, method, and so on
315 | - `requestKey`: Either the computed request key, or the value of the
316 | `requestKey` prop
317 | - `response`: The response that was received from the HTTP request
318 | - `data`: The transformed data from the response. This will be different from
319 | `response.data` if a `transformData` function was passed as a prop to ``.
320 | - `error`: An error returned from the HTTP request
321 | - `didUnmount`: A Boolean representing whether or not the component has unmounted
322 |
323 | This can be used for analytics or syncing response data with a data store such
324 | as [Redux](https://github.com/reactjs/redux/).
325 |
326 | > Note: This function is not called when the component reads from the cache.
327 |
328 | ##### `props.onResponse`
329 |
330 | A function that is called every time a response is received, whether that
331 | response is from the cache or from a network request. Receives two arguments:
332 | `error` and `response`.
333 |
334 | ```jsx
335 | {
338 | if (error) {
339 | console.log('Ruh roh', error);
340 | } else {
341 | console.log('Got a response!', response);
342 | }
343 | }}>
344 | {() => {
345 |
Hello
;
346 | }}
347 |
348 | ```
349 |
350 | ##### `props.transformData`
351 |
352 | A function that is called with the data returned from the response. You can use this
353 | hook to transform the data before it is passed into `children`.
354 |
355 | ```jsx
356 | data.post>
359 | {({ fetching, error, response, data }) => {
360 |
370 | }}
371 |
372 | ```
373 |
374 | > Note: `transformData` does not modify the value of `response.data`. The transformed data is
375 | > made available to you in the [render prop argument](#children) under the `data` key.
376 |
377 | ##### `props.responseType`
378 |
379 | The content type of the response body. Defaults to `"json"` unless the response has a 204 status code,
380 | in which case it will be `"text"` instead. Valid values are any of the methods on
381 | [Body](https://developer.mozilla.org/en-US/docs/Web/API/Body).
382 |
383 | Alternatively, you may specify a function that returns a string. The function will be called with one
384 | argument: `response`. This allows you to dynamically specify the response type based on information
385 | about the response, such as its status code.
386 |
387 | ```jsx
388 | // If you have an endpoint that just returns raw text, you could, for instance, convert it into
389 | // an object using `responseType` and `transformData`.
390 | {
394 | return {
395 | countryName,
396 | };
397 | }}>
398 | {({ data }) => {
399 | if (data) {
400 | return
{data.countryName}
;
401 | }
402 |
403 | return null;
404 | }}
405 |
406 | ```
407 |
408 | If the response body cannot be parsed as the `responseType` that you specify, then `data` will
409 | be set to `null`.
410 |
411 | ##### `props.requestName`
412 |
413 | A name to give this request, which can help with debugging purposes. The request name is
414 | analogous to a function name in JavaScript. Although we could use anonymous functions
415 | everywhere, we tend to give them names to help humans read and debug the code.
416 |
417 | ```jsx
418 |
419 | ```
420 |
421 | > Note: This feature is analogous to the [operation name](http://graphql.org/learn/queries/#operation-name) in GraphQL.
422 |
423 | ##### `props.fetchPolicy`
424 |
425 | This determines how the request interacts with the cache. Valid options are:
426 |
427 | - `"cache-first"`
428 | - `"cache-and-network"`
429 | - `"network-only"`
430 | - `"cache-only"`
431 |
432 | For documentation on what each of these values do, refer to the [response caching guide](./docs/guides/response-caching.md).
433 |
434 | The default value of this prop is based on the value of the `method` prop that you pass to ``.
435 |
436 | | Method | Default value |
437 | | ------------------------ | ---------------- |
438 | | GET, HEAD, OPTIONS | `"cache-first"` |
439 | | POST, PUT, PATCH, DELETE | `"network-only"` |
440 |
441 | > This prop behaves identically to the Apollo prop
442 | > [with the same name](https://www.apollographql.com/docs/react/basics/queries.html#graphql-config-options-fetchPolicy).
443 |
444 | ##### `props.cacheResponse`
445 |
446 | Whether or not the response will be cached. The default value is based on the value of the `method` prop that you pass
447 | to ``.
448 |
449 | | Method | Default value |
450 | | ------------------------ | ------------- |
451 | | GET, HEAD, OPTIONS | `true` |
452 | | POST, PUT, PATCH, DELETE | `false` |
453 |
454 | For documentation on this prop, refer to the [response caching guide](./docs/guides/response-caching.md).
455 |
456 | ##### `props.dedupe`
457 |
458 | A Boolean value representing whether or not the request should be
459 | [deduplicated](./docs/guides/request-deduplication.md).
460 | Defaults to `true`.
461 |
462 | ##### `props.requestKey`
463 |
464 | A string that is used to control the request deduplication and response caching features. By default,
465 | a key is generated for you. Specifying a custom key is an advanced feature that you may not need.
466 |
467 | For more, see the [request key](https://github.com/jamesplease/react-request/blob/master/docs/guides/request-keys.md)
468 | guide.
469 |
470 | ---
471 |
472 | The rest of the API documentation describes the other named exports from the `react-request` package. Typically,
473 | you won't need to use these, but they are available should you need them.
474 |
475 | #### `fetchDedupe( input [, init] [, dedupeOptions] )`
476 |
477 | This is the `fetchDedupe` export from the [Fetch Dedupe](https://github.com/jamesplease/fetch-dedupe)
478 | library. Fetch Dedupe powers the request deduplication in React Request.
479 |
480 | Whenever you need to make a standalone HTTP request outside of the
481 | `` component, then you can use this with confidence that you won't send a
482 | duplicate request.
483 |
484 | For more, refer to [the documentation of fetch-dedupe](https://github.com/jamesplease/fetch-dedupe).
485 |
486 | #### `getRequestKey({ url, method, body, responseType })`
487 |
488 | Generates a request key. All of the values are optional. You typically never need to use this, as request
489 | keys are generated automatically for you when you use React Request or Fetch Dedupe.
490 |
491 | This method comes from [`fetch-dedupe`](https://github.com/jamesplease/fetch-dedupe).
492 |
493 | #### `isRequestInFlight( requestKey )`
494 |
495 | Return a Boolean representing if a request for `requestKey` is in flight or not.
496 |
497 | This method comes from [`fetch-dedupe`](https://github.com/jamesplease/fetch-dedupe).
498 |
499 | #### `clearRequestCache()`
500 |
501 | Wipes the cache of deduped requests. Mostly useful for testing.
502 |
503 | This method comes from [`fetch-dedupe`](https://github.com/jamesplease/fetch-dedupe).
504 |
505 | > Note: this method is not safe to use in application code.
506 |
507 | #### `clearResponseCache()`
508 |
509 | Wipes the cache of cached responses. Mostly useful for testing.
510 |
511 | > Note: this method is not safe to use in application code.
512 |
513 | ### Acknowledgements
514 |
515 | This library was inspired by [Apollo](https://www.apollographql.com). The
516 | library [Holen](https://github.com/tkh44/holen) was referenced during the
517 | creation of this library.
518 |
--------------------------------------------------------------------------------
/ROADMAP.md:
--------------------------------------------------------------------------------
1 | # Roadmap
2 |
3 | This roadmap outlines future changes to React Request.
4 |
5 | ### Next release
6 |
7 | * [ ] `doFetch` will return a Promise
8 | * [ ] A serial requests story will be more defined. Right now, it isn't super clear how to do it.
9 |
10 | ### Sometime later
11 |
12 | * [ ] The caching implementation will be moved to `fetch-dedupe`. This is a non-breaking change.
13 | * [ ] Caching and deduplication will support an array, allowing for a more sophisticated system that
14 | supports multi-operational HTTP requests (GraphQL, for instance)
15 | * [ ] Implement "true" aborting rather than the "fake" aborting currently in the lib
16 | * [ ] Add an Abort API
17 |
--------------------------------------------------------------------------------
/docs/FAQ.md:
--------------------------------------------------------------------------------
1 | # FAQ
2 |
3 | Here are some answers to common questions. Don't see yours here?
4 | [Open an issue](https://github.com/jamesplease/react-request/issues/new) and
5 | we would be happy to help.
6 |
7 | #### Why was this created?
8 |
9 | While I was studying Apollo, a framework for GraphQL, I learned that its React library exports a
10 | higher-order component that enables a developer to declaratively specify HTTP requests. It surprised me
11 | that this was the primary method that Apollo developers were interfacing with GraphQL over HTTP.
12 |
13 | It didn't take long for me to understand that the Apollo HoC was remarkably useful. And although some of the features
14 | that it provides only make sense in the context of GraphQL, I noticed that other features, such as request
15 | deduplication and response caching, would be incredibly useful to any developer who is writing React code.
16 |
17 | The only problem is that you can't use Apollo's HoC unless you use GraphQL. This is why I wrote React Request:
18 | to abstract this functionality out into a general-use component.
19 |
20 | #### Why would anyone want to use JSX for making HTTP requests?
21 |
22 | I was skeptical at first, too, but it turns out that many of the complex things people do with HTTP requests (namely,
23 | request deduplication and response caching) map nicely to the component lifecycle. You can remove a considerable amount
24 | of difficult-to-test imperative code from your application by declaratively specifying how you want your requests to
25 | behave through JSX.
26 |
27 | #### If a request is made when the component mounts, how does that work for POST, PATCH, or DELETE requests?
28 |
29 | The default behavior is that requests are only made on mount for `GET` requests when the component mounts, and
30 | not for those other HTTP methods.
31 |
32 | One of the things that is passed into the render prop function is a method called `fetch`. Calling this method will perform
33 | the request. This allows you to hook up, say, a PATCH request to a button.
34 |
35 | Whether or not the request makes a request on mount can be customized with the `lazy` prop.
36 |
37 | #### What if I just want a regular fetch component without deduplication or caching features?
38 |
39 | Take a look at [Holen](https://github.com/tkh44/holen).
40 |
41 | #### What about normalization of data? Apollo does this.
42 |
43 | That requires a definition of what a "resource" (or "entity") is, which is a little bit too opinionated for this
44 | library.
45 |
46 | With that said, this library is an excellent tool to use to build React bindings for a more opinionated framework
47 | that does define a resource or entity. For instance, the [Redux Resource](https://redux-resource.js.org) React bindings
48 | will be built using React Request.
49 |
50 | #### Why isn't this a higher-order component like Apollo's `graphql`?
51 |
52 | The render prop pattern is more powerful than Higher Order Components. Read
53 | [this post](https://cdb.reacttraining.com/use-a-render-prop-50de598f11ce) for more.
54 |
55 | In an upcoming version of React Apollo, they, too, will export render prop components.
56 |
57 | #### Why is the prop named `children` rather than `render`?
58 |
59 | Although there are a handful of arguments for the render prop to be `render` rather than `children`, this library is
60 | using the same pattern that React's [new Context API](https://github.com/reactjs/rfcs/pull/2) uses.
61 |
--------------------------------------------------------------------------------
/docs/examples.md:
--------------------------------------------------------------------------------
1 | # Examples
2 |
3 | A number of examples are distributed with the library's
4 | [source code](https://github.com/jamesplease/react-request).
5 |
6 | ### Simple Read
7 |
8 | To run this example:
9 |
10 | ```
11 | git clone https://github.com/jamesplease/react-request.git
12 |
13 | cd react-request/examples/simple-read
14 | npm install
15 | npm start
16 |
17 | open http://localhost:3000/
18 | ```
19 |
20 | This example shows a simple request that fetches a single resource
21 | when the component mounts.
22 |
23 | ### Lazy Read
24 |
25 | To run this example:
26 |
27 | ```
28 | git clone https://github.com/jamesplease/react-request.git
29 |
30 | cd react-request/examples/lazy-read
31 | npm install
32 | npm start
33 |
34 | open http://localhost:3000/
35 | ```
36 |
37 | In this example, the request is defined as lazy, so it isn't made
38 | when the component first mounts. Instead, the user of the application
39 | must click a button to make the request.
40 |
41 | ### Updating a Resource
42 |
43 | To run this example:
44 |
45 | ```
46 | git clone https://github.com/jamesplease/react-request.git
47 |
48 | cd react-request/examples/updating-a-resource
49 | npm install
50 | npm start
51 |
52 | open http://localhost:3000/
53 | ```
54 |
55 | Requests with the headers `POST`, `PUT`, `PATCH`, or `DELETE` are lazy
56 | by default. This example demonstrates how these sorts of requests are
57 | typically used in your application.
58 |
59 | ### Multiple Requests
60 |
61 | To run this example:
62 |
63 | ```
64 | git clone https://github.com/jamesplease/react-request.git
65 |
66 | cd react-request/examples/multiple-requests
67 | npm install
68 | npm start
69 |
70 | open http://localhost:3000/
71 | ```
72 |
73 | Sometimes, you will need access to multiple requests at the same time. This
74 | example demonstrates using the [React Composer](https://github.com/jamesplease/react-composer)
75 | library to do that.
76 |
77 | ### Request Deduplication
78 |
79 | To run this example:
80 |
81 | ```
82 | git clone https://github.com/jamesplease/react-request.git
83 |
84 | cd react-request/examples/request-deduplication
85 | npm install
86 | npm start
87 |
88 | open http://localhost:3000/
89 | ```
90 |
91 | This example demonstrates how many requests of the same kind are deduplicated by default.
92 |
93 | ### Response Caching
94 |
95 | To run this example:
96 |
97 | ```
98 | git clone https://github.com/jamesplease/react-request.git
99 |
100 | cd react-request/examples/response-caching
101 | npm install
102 | npm start
103 |
104 | open http://localhost:3000/
105 | ```
106 |
107 | Response caching comes built into React Request. This example shows the default
108 | `fetchPolicy` that returns data from the cache when it is available, rather than
109 | making a second request.
110 |
111 | ### Fetch Components
112 |
113 | To run this example:
114 |
115 | ```
116 | git clone https://github.com/jamesplease/react-request.git
117 |
118 | cd react-request/examples/fetch-components
119 | npm install
120 | npm start
121 |
122 | open http://localhost:3000/
123 | ```
124 |
125 | Often times, configuring HTTP requests requires, well, a lot of configuration, such as headers,
126 | the URL, and the cache policy.
127 |
128 | Rather than repeating this throughout your app, you can clean things up by creating "fetch components,"
129 | an organizational strategy where the `` components themselves are placed into standalone files.
130 |
--------------------------------------------------------------------------------
/docs/guides/INDEX.md:
--------------------------------------------------------------------------------
1 | # Guides
2 |
3 | These guides provide tips and additional information that can help you use React Request.
4 |
5 | * [Response Caching](./response-caching.md)
6 | * [Request Deduplication](./request-deduplication.md)
7 | * [Request Keys](./request-keys.md)
8 | * [Best Practices](./best-practices.md)
9 | * [Using the `lazy` Prop](./using-the-lazy-prop.md)
10 | * [Aborting](./aborting.md)
11 | * [Differences with `fetch()`](./differences-with-fetch.md)
12 | * [Differences with React Apollo](./differences-with-react-apollo.md)
13 | * [Integration with Other Technologies](./integration-with-other-technologies.md)
14 |
--------------------------------------------------------------------------------
/docs/guides/aborting.md:
--------------------------------------------------------------------------------
1 | # Aborting Requests
2 |
3 | Browsers will soon support an API to allow developers to
4 | [abort fetches](https://developers.google.com/web/updates/2017/09/abortable-fetch). Aborting
5 | requests within React Request currently is not currently supported, but it is on the
6 | project roadmap.
7 |
8 | For more, refer to [this GitHub issue](https://github.com/jamesplease/react-request/issues/26).
9 |
10 | ### Pseudo-aborts
11 |
12 | The `` component will "pseudo-abort" requests. With a faux-abort, the actual HTTP request
13 | will not be aborted, but there are situations when the response will be ignored:
14 |
15 | 1. When the component unmounts
16 | 2. When a new request is initiated while an existing request is already in flight
17 |
18 | In these situations, `onResponse` will be called with an error that has a `name` equal
19 | to `AbortError`.
20 |
21 | ### Warning: don't use the `signal` prop
22 |
23 | You may be tempted to use the `signal` prop of `` to abort requests, but this
24 | may not work as well as you would like it to. The `` component will make a new
25 | request anytime a new [request key](./request-keys.md) is generated from the props that
26 | you pass in.
27 |
28 | This means that you would need to create a new `AbortController` any time that there is
29 | a new request key. Although this may work for limited use cases, it does not scale well,
30 | so we do not recommend it as a general practice.
31 |
--------------------------------------------------------------------------------
/docs/guides/best-practices.md:
--------------------------------------------------------------------------------
1 | # Best Practices
2 |
3 | Here are some tips that may help you when using React Request.
4 |
5 | ### Handling errors
6 |
7 | The `failed` Boolean is passed to the `children` callback, which
8 | represents whether _any_ error occurred with the request. This includes
9 | network requests or status codes greater than or equal to 400.
10 |
11 | This Boolean is convenient for a coarse understanding that the network
12 | failed, but using this Boolean alone is typically not enough to provide
13 | a great user experience. A user may want to know why the request
14 | failed. Was the resource not found? Did the user submit bad information?
15 | Was there a network error? Was the user logged out?
16 |
17 | We encourage you to dig into the `error` and `response` objects
18 | to provide your users with a more detailed explanation of what went wrong,
19 | rather than displaying a generic "There was an error" message.
20 |
21 | Here is an example that shows the different kinds of ways that a response
22 | can error.
23 |
24 | ```js
25 |
26 | {({ failed, error, response }) => {
27 | if (failed) {
28 | console.log('There was _some_ kind of error. What happened?');
29 | }
30 |
31 | if (error) {
32 | console.log('There was a network error');
33 |
34 | if (!navigation.onLine) {
35 | console.log('The user lost internet connection.');
36 | } else {
37 | // You can look at the Error object to learn even details.
38 | console.log('The request was aborted, or it timed out');
39 | }
40 | }
41 |
42 | const status = response && response.status;
43 |
44 | if (status === 404) {
45 | console.log('The resource was not found.');
46 | } else if (status === 401) {
47 | console.log('You user have been logged out.');
48 | } else if (status === 400) {
49 | console.log('Invalid data was submitted');
50 | } else if (status === 500) {
51 | console.log('Something went wrong on the server.');
52 | }
53 | }}
54 |
55 | ```
56 |
57 | ### Making "fetch components"
58 |
59 | HTTP requests require a lot of configuration, which can make your
60 | application code messy. One way to clean this up is to make
61 | "fetch components" that simplify the API to make a request.
62 |
63 | For instance, if your application manages books, you may have these
64 | fetch components:
65 |
66 | ```jsx
67 | // books.js
68 | import React from 'react';
69 | import { Fetch } from 'react-request';
70 | import headers from './utils/default-request-headers';
71 | import httpAnalytics from './utils/http-analytics';
72 |
73 | export function ReadBook({ bookId, children }) {
74 | return (
75 |
82 | );
83 | }
84 |
85 | export function DeleteBook({ bookId, children }) {
86 | return (
87 |
95 | );
96 | }
97 | ```
98 |
99 | This makes it so you only need to specify things like credentials,
100 | headers, and analytics in a single place.
101 |
102 | You can use these components in your application like so:
103 |
104 | ```jsx
105 | import React, { Component } from 'react';
106 | import { readBook } from './request-components/books';
107 |
108 | export default class App extends Component {
109 | render() {
110 | const { bookId } = this.props;
111 |
112 | return (
113 |
114 |
Welcome to My App
115 |
116 | {result => {
117 | // Use the result here
118 | }}
119 |
120 |
121 | );
122 | }
123 | }
124 | ```
125 |
126 | If you've used [Redux](https://redux.js.org) for HTTP requests in the past, then you can think of the
127 | "fetch components" as fulfilling a similar role as action creators. They cut down on the boilerplate.
128 |
129 | ### Directory Structure
130 |
131 | We recommend organizing your fetch components by their resource type. For instance, if your app manages
132 | books, authors, and publishers, you might have:
133 |
134 | ```
135 | /src
136 | /fetch-components
137 | books.js
138 | authors.js
139 | publishers.js
140 | ```
141 |
142 | Within each of those resource files, you might have multiple "fetch components" for reading and updating
143 | the resources in various ways.
144 |
--------------------------------------------------------------------------------
/docs/guides/differences-with-apollo.md:
--------------------------------------------------------------------------------
1 | # Differences with Apollo
2 |
3 | React Apollo is a great library, and it served as the primary inspiration for React Request.
4 | There are a few places where this library is different from React Apollo.
5 |
6 | ### Missing Features
7 |
8 | React Request is intended to be relatively lightweight, so it does not implement these
9 | features or props from React Apollo:
10 |
11 | * Polling
12 | * Optimistic responses
13 | * `errorPolicy` prop
14 | * `notifyOnNetworkStatusChange` prop
15 |
16 | The reason for these omissions is that we believe that you can implement this features in your
17 | application, or in a wrapping component, without too much extra work. If you disagree, open an issue –
18 | we may very well be wrong!
19 |
20 | ### One component
21 |
22 | React Apollo provides two components, one for Queries and the other for Mutations. React Request provides
23 | just the one. When working with HTTP without the GraphQL, it doesn't make as much sense to split out reads
24 | and writes from one another.
25 |
26 | ### Requesting on mount
27 |
28 | With Apollo, whether or not the request is made when the component mounts depends on if it is a mutation or
29 | a query. React Request looks at the HTTP method instead to determine if the request is _likely_ a read request or a write request.
30 |
31 | ### No Data Normalization
32 |
33 | React Apollo normalizes your data, and makes it available through the store. This requires a
34 | definition of a "resource" or "entity," which is beyond the scope of this library.
35 |
36 | If you want data normalization, you need two things:
37 |
38 | 1. a location to place the normalized data in memory (typically called a store)
39 | 2. a library or framework that defines what a resource or entity is
40 |
41 | For instance, [Redux](https://redux.js.org) can fulfill the role of item 1 while
42 | [Redux Resource](https://redux-resource.js.org) can fulfill the role of item 2.
43 |
44 | Once you have those two things, you can use React Request to provide declarative
45 | requests (in fact, the official React bindings for Redux Resource will be built
46 | using React Request).
47 |
--------------------------------------------------------------------------------
/docs/guides/differences-with-fetch.md:
--------------------------------------------------------------------------------
1 | # Differences with `fetch()`
2 |
3 | Whenever possible, we try to follow standard usage of the
4 | [`fetch()`](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch)
5 | API as closely as possible. There are a few differences between using `fetch()` and this
6 | library, though, which are explained here.
7 |
8 | ### `init` is not an Object
9 |
10 | The second argument to `fetch()` is an optional object called `init`. With
11 | ``, the object has been spread out as props. This change was made
12 | for aesthetic reasons: I find it ugly to pass objects as props.
13 |
14 | ```js
15 | fetch('/posts/2', {
16 | method: 'PATCH',
17 | credentials: 'include',
18 | body: JSON.stringify({ title: 'New post' })
19 | });
20 | ```
21 |
22 | ```jsx
23 |
29 | ```
30 |
31 | ### The response body is read for you
32 |
33 | When using `fetch`, you must manually read the body. This
34 | library reads it automatically for you. This is because the body
35 | is a ReadableStream, and can only be read a single time. It was
36 | a requirement that React Request read it for you to support
37 | [deduplication of requests](./request-deduplication.md).
38 |
39 | ```js
40 | fetch('/posts/2', {
41 | method: 'PATCH',
42 | credentials: 'include',
43 | body: JSON.stringify({ title: 'New post' })
44 | })
45 | .then(res => res.body.json())
46 | .then(data => {
47 | console.log('Got my JSON', data);
48 | });
49 | ```
50 |
51 | ```jsx
52 |
57 | {({ data }) => {
58 | console.log('Got my JSON', data);
59 | return null;
60 | }}
61 |
62 | ```
63 |
64 | ### Only string request bodies are supported
65 |
66 | For now, you may only pass strings as the request body. This is
67 | due to the fact that we need to build a request key for
68 | [request deduplication](./request-deduplication.md) and
69 | response caching.
70 |
71 | In the future, we plan to add support for additional request body types.
72 |
73 | ### Aborting requests
74 |
75 | When aborting `fetch()`, you will typically do the following:
76 |
77 | 1. Create an AbortController object
78 | 2. Pass the AbortSignal object into `fetch`
79 |
80 | This system does not work with ``, because it would be tedious
81 | for you to create a new AbortController anytime the component was going
82 | to make a new request.
83 |
84 | It is on our roadmap to provide a great story around aborting requests. For
85 | more, see the guide on [aborting requests](./aborting.md).
86 |
--------------------------------------------------------------------------------
/docs/guides/integration-with-other-technologies.md:
--------------------------------------------------------------------------------
1 | # Integration with Other Technologies
2 |
3 | React Request was designed to integrate well with other tools in the ecosystem.
4 |
5 | ### GraphQL
6 |
7 | At the moment, a system like Apollo or Relay is better suited for GraphQL.
8 |
9 | The reason for this is that React Request only caches and dedupes at the _request level_,
10 | whereas a library like Apollo caches and dedupes at the sub-request level.
11 |
12 | This is important because GraphQL allows you to embed multiple operations into a single
13 | HTTP request.
14 |
15 | > Note: multiple operation request support is on the roadmap for this project.
16 |
17 | ### Redux
18 |
19 | Data returned by your server can be synchronized with your Redux store. The
20 | `beforeFetch` and `afterFetch` methods make this straightforward to do.
21 |
22 | The following example demonstrates how you might go about doing this:
23 |
24 | ```jsx
25 | {
28 | store.dispatch({
29 | type: 'FETCH_PENDING'
30 | // ...add whatever you want here
31 | });
32 | }}
33 | afterFetch={data => {
34 | if (data.error || (data.response && !data.response.ok)) {
35 | store.dispatch({
36 | type: 'FETCH_FAILED'
37 | // ...add other things to this action
38 | });
39 | } else {
40 | store.dispatch({
41 | type: 'FETCH_SUCCEEDED'
42 | // ...add other things to this action
43 | });
44 | }
45 | }}
46 | />
47 | ```
48 |
49 | ### Redux Resource
50 |
51 | React Request was built with [Redux Resource](https://redux-resource.js.org) in mind.
52 | An official library that provides React bindings for Redux Resource is in the works, and it
53 | will use React Request.
54 |
55 | ### React Native
56 |
57 | React Request may work in React Native. I am not sure, because I haven't used React Native
58 | before.
59 |
60 | Before you try it out, be sure to include the polyfill for
61 | [a global object](https://github.com/johanneslumpe/react-native-browser-polyfill/blob/25a736aac89e5025d49a8ca10b01bb1a81cd6ce7/polyfills/globalself.js).
62 |
--------------------------------------------------------------------------------
/docs/guides/request-deduplication.md:
--------------------------------------------------------------------------------
1 | # Request Deduplication
2 |
3 | React Request will prevent two identical HTTP requests from being in flight at the
4 | same time. It does this by comparing the [request key](./request-keys.md) of any
5 | new request with the keys of all in-flight requests.
6 |
7 | When an existing request is already in flight for that same key, then a new
8 | request will not be dispatched. Instead, the same response will be sent to
9 | both requestors.
10 |
11 | ### Examples
12 |
13 | In the following example, only one HTTP request is made:
14 |
15 | ```jsx
16 | class App extends Component {
17 | render() {
18 | return (
19 |
20 |
21 |
22 |
23 | );
24 | }
25 | }
26 | ```
27 |
28 | However, in this example, two requests are made because the URLs are different, resulting in
29 | a different request key:
30 |
31 | ```jsx
32 | class App extends Component {
33 | render() {
34 | return (
35 |
36 |
37 |
38 |
39 | );
40 | }
41 | }
42 | ```
43 |
44 | ### Reliability
45 |
46 | The default request key implementation assumes that `JSON.stringify` will produce the same string given two different objects
47 | that would be considered "deeply equal" (for instance, if they were compared using [`_.isEqual`](https://lodash.com/docs/#isEqual)).
48 |
49 | This may seem unreliable to you, but Apollo
50 | [has been doing it this way for some time](https://github.com/apollographql/apollo-link/blob/d5b0d4c491563ed36c50170e0b4c6c5f8c988d59/packages/apollo-link/src/linkUtils.ts#L121-L127),
51 | and that is a library with half a million downloads per month (as of February 2018). So it seems to
52 | be reliable.
53 |
54 | Needless to say, if this behavior ever causes problems, then we will revisit the approach.
55 |
56 | ### Disabling deduplication
57 |
58 | You can disable deduplication with the `dedupe` prop.
59 |
60 | ```jsx
61 | // In this example, two identical HTTP requests will be made at the same time.
62 | class App extends Component {
63 | render() {
64 | return (
65 |
66 |
67 |
68 |
69 | );
70 | }
71 | }
72 | ```
73 |
--------------------------------------------------------------------------------
/docs/guides/request-keys.md:
--------------------------------------------------------------------------------
1 | # Request Keys
2 |
3 | React Request's two most useful features are
4 | [request deduplication](./request-deduplication.md) and
5 | [response caching](./response-caching.md).
6 |
7 | Both of these features are powered by a system called "request keys," which are strings that
8 | allow React Request to determine if two requests are to be considered identical.
9 |
10 | ### What is a Request Key
11 |
12 | A request key is a string that is created from the props that you pass to `Fetch`.
13 |
14 | The key is composed of these pieces of information:
15 |
16 | * `url`
17 | * `method`
18 | * `body`
19 |
20 | ### How is it Used
21 |
22 | **Request Deduplication**
23 |
24 | When two or more `` components with the same key attempt to fire off a request, only one HTTP
25 | request will be sent off. When the response is returned, all of the components will
26 | receive that single response.
27 |
28 | For more, see the guide on [request deduplication](./request-deduplication.md).
29 |
30 | **Response Caching**
31 |
32 | Anytime a response is received for a request, it is stored in an internal cache. If
33 | a subsequent request is attempted with the same key, then the cached version
34 | will be returned instead.
35 |
36 | For more, see the guide on [response caching](./response-caching.md).
37 |
--------------------------------------------------------------------------------
/docs/guides/response-caching.md:
--------------------------------------------------------------------------------
1 | # Response Caching
2 |
3 | React Request has a built-in response caching system. Interactions with the
4 | cache are configurable with the `fetchPolicy` and `cacheResponse` prop.
5 |
6 | The way the cache works is like this: any time a response from the server is received,
7 | it will be cached using the request's [request key](./request-keys.md). Subsequent
8 | requests are matched with existing cached server responses using _their_ request key.
9 |
10 | The `cacheResponse` prop determines if server responses will be cached. Typically,
11 | you only want to cache responses for "read" requests. Accordingly, the default
12 | value is based on the value of the `method` prop:
13 |
14 | | Method | Default value |
15 | | ------------------------ | ------------- |
16 | | GET, HEAD, OPTIONS | `true` |
17 | | POST, PUT, PATCH, DELETE | `false` |
18 |
19 | There are four ways that a `` component can interact with the
20 | cached responses, which are configurable with the `fetchPolicy` prop:
21 |
22 | ### `cache-first`
23 |
24 | This is the default behavior.
25 |
26 | Requests will first look at the cache to see if a response for the same key exists. If a response is
27 | found, then it will be returned, and no network request will be made.
28 |
29 | If no response exists in the cache, then a network request will be made.
30 |
31 | ### `cache-and-network`
32 |
33 | Requests will first look at the cache. If a response exists in the cache,
34 | then it will immediately be returned.
35 |
36 | Whether or not a response exists in the cache, a network request will be made.
37 |
38 | ### `network-only`
39 |
40 | The cache is ignored, and a network request is always made.
41 |
42 | ### `cache-only`
43 |
44 | If a response exists in the cache, then it will be returned. If no response
45 | exists in the cache, then an error will be passed into the render prop function.
46 |
47 | ---
48 |
49 | Like `cacheResponse`, the default value of `fetchPolicy` is based on the method that you pass.
50 |
51 | | Method | Default value |
52 | | ------------------------ | ---------------- |
53 | | GET, HEAD, OPTIONS | `"cache-first"` |
54 | | POST, PUT, PATCH, DELETE | `"network-only"` |
55 |
56 | ### Using `POST` for read requests
57 |
58 | Some APIs use the `POST` method for read requests. React Request supports this, but you will
59 | need to manually configure the cache. This may look something like this:
60 |
61 | ```jsx
62 |
69 | ```
70 |
71 | With the above configuration, responses will be stored in the cache, and requests will
72 | only be made when the cache is empty. Also note that the [lazy prop](./using-the-lazy-prop.md)
73 | is set to `false` so that the request fires when the component mounts.
74 |
--------------------------------------------------------------------------------
/docs/guides/using-the-lazy-prop.md:
--------------------------------------------------------------------------------
1 | # Using the `lazy` Prop
2 |
3 | One of the props of the `` component is `lazy`. This
4 | determines whether or not a request will be made when the
5 | component mounts.
6 |
7 | The default value of `lazy` depends on the request method
8 | being used.
9 |
10 | | Method | Default value |
11 | | ------------------------ | ------------- |
12 | | GET, HEAD, OPTIONS | `false` |
13 | | POST, PUT, PATCH, DELETE | `true` |
14 |
15 | This is due to the way applications typically use these methods
16 | when performing reads and writes.
17 |
18 | ### Read Requests
19 |
20 | Read requests are frequently done as a result of the user navigating
21 | to some section of the page. For instance, if your application is for
22 | a library, and the user visits the URL `/books/2`, then you will likely
23 | want to kick off a request to fetch that book right after the page loads.
24 |
25 | This is why `lazy` is `false` for `GET` requests.
26 |
27 | > Sometimes, APIs will use `POST` for read requests. In these situations, you will
28 | need to manually specify `lazy` as `false` if you would like to make the request
29 | when the component mounts.
30 |
31 | ### Write Requests
32 |
33 | Typically, write requests, such as updating or deleting a resource, are not done
34 | as the result of a user simply navigating to a page. Instead, these are typically
35 | performed when a user clicks a button to confirm the action.
36 |
37 | This is why `lazy` is `true` for HTTP methods that typically refer to write requests.
38 |
39 | ### Dynamic `lazy` prop usage
40 |
41 | A neat pattern is to specify a dynamic `lazy` value based on some application state. For
42 | instance, consider a search page that serializes the user's search into a query parameter.
43 |
44 | When the app loads, you may want to make the request immediately when the query parameter
45 | exists. But if there isn't a query parameter, then you won't want to make the request, because
46 | there's no search term to use in the request.
47 |
48 | You can use a dynamic value for `lazy` to implement this behavior. The example below
49 | demonstrates how you might go about doing this.
50 |
51 | ```jsx
52 |
53 | {children}
54 |
55 | ```
56 |
--------------------------------------------------------------------------------
/examples/fetch-components/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 |
6 | # testing
7 | /coverage
8 |
9 | # production
10 | /build
11 |
12 | # misc
13 | .DS_Store
14 | .env.local
15 | .env.development.local
16 | .env.test.local
17 | .env.production.local
18 |
19 | npm-debug.log*
20 | yarn-debug.log*
21 | yarn-error.log*
22 |
--------------------------------------------------------------------------------
/examples/fetch-components/README.md:
--------------------------------------------------------------------------------
1 | # Fetch Components
2 |
3 | This project template was built with [Create React App](https://github.com/facebookincubator/create-react-app), which provides a simple way to start React projects with no build configuration needed.
4 |
5 | Projects built with Create-React-App include support for ES6 syntax, as well as several unofficial / not-yet-final forms of Javascript syntax such as Class Properties and JSX. See the list of [language features and polyfills supported by Create-React-App](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#supported-language-features-and-polyfills) for more information.
6 |
7 | ## Available Scripts
8 |
9 | In the project directory, you can run:
10 |
11 | ### `npm start`
12 |
13 | Runs the app in the development mode.
14 | Open [http://localhost:3000](http://localhost:3000) to view it in the browser.
15 |
16 | The page will reload if you make edits.
17 | You will also see any lint errors in the console.
18 |
19 | ### `npm run build`
20 |
21 | Builds the app for production to the `build` folder.
22 | It correctly bundles React in production mode and optimizes the build for the best performance.
23 |
24 | The build is minified and the filenames include the hashes.
25 | Your app is ready to be deployed!
26 |
27 | ### `npm run eject`
28 |
29 | **Note: this is a one-way operation. Once you `eject`, you can’t go back!**
30 |
31 | If you aren’t satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project.
32 |
33 | Instead, it will copy all the configuration files and the transitive dependencies (Webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own.
34 |
35 | You don’t have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it.
36 |
--------------------------------------------------------------------------------
/examples/fetch-components/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "fetch-components",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "react": "^16.2.0",
7 | "react-composer": "^4.1.0",
8 | "react-dom": "^16.2.0",
9 | "react-request": "^3.0.0",
10 | "react-scripts": "1.1.0"
11 | },
12 | "scripts": {
13 | "start": "react-scripts start",
14 | "build": "react-scripts build",
15 | "test": "react-scripts test --env=jsdom",
16 | "eject": "react-scripts eject"
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/examples/fetch-components/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jamesplease/react-request/efda7bdcc083b9b956203ce6ef5eefadc6b36aa5/examples/fetch-components/public/favicon.ico
--------------------------------------------------------------------------------
/examples/fetch-components/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
11 |
12 |
13 |
22 | React App
23 |
24 |
25 |
28 |
29 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/examples/fetch-components/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "64x64 32x32 24x24 16x16",
8 | "type": "image/x-icon"
9 | }
10 | ],
11 | "start_url": "./index.html",
12 | "display": "standalone",
13 | "theme_color": "#000000",
14 | "background_color": "#ffffff"
15 | }
16 |
--------------------------------------------------------------------------------
/examples/fetch-components/src/App.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import Composer from 'react-composer';
3 | import { ReadPost, UpdatePost, DeletePost } from './fetch-components/posts';
4 |
5 | class App extends Component {
6 | render() {
7 | // This ID could come from, say, props
8 | const postId = '1';
9 |
10 | return (
11 | ,
14 | ,
15 | ,
16 | ]}>
17 | {([readPost, updatePost, deletePost]) => (
18 |
19 |
20 |
29 |
44 |
45 |
46 | {readPost.fetching && 'Loading...'}
47 | {readPost.failed && 'There was some kind of error'}
48 | {readPost.data && (
49 |
50 |
Post title: {readPost.data.title}
51 |
Post ID: {readPost.data.id}
52 |
53 | )}
54 |
55 |
56 | )}
57 |
58 | );
59 | }
60 | }
61 |
62 | export default App;
63 |
--------------------------------------------------------------------------------
/examples/fetch-components/src/fetch-components/posts.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Fetch } from 'react-request';
3 |
4 | // The idea behind this is to abstract away your HTTP request configuration.
5 | // Typically, you don't want things like URLs and header configuration scattered
6 | // throughout your app.
7 | //
8 | // This allows you to reuse all of that HTTP configuration in your app by
9 | // passing the minimum amount of information necessary to make the request.
10 | //
11 | // In the case of this simple "post" resource, all that is needed is an ID (and
12 | // children, since Fetch is a render prop component)
13 |
14 | export function ReadPost({ postId, children }) {
15 | return (
16 |
20 | );
21 | }
22 |
23 | export function UpdatePost({ postId, children }) {
24 | return (
25 |
30 | );
31 | }
32 |
33 | export function DeletePost({ postId, children }) {
34 | return (
35 |
40 | );
41 | }
42 |
--------------------------------------------------------------------------------
/examples/fetch-components/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import App from './App';
4 |
5 | ReactDOM.render(, document.getElementById('root'));
6 |
--------------------------------------------------------------------------------
/examples/lazy-read/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 |
6 | # testing
7 | /coverage
8 |
9 | # production
10 | /build
11 |
12 | # misc
13 | .DS_Store
14 | .env.local
15 | .env.development.local
16 | .env.test.local
17 | .env.production.local
18 |
19 | npm-debug.log*
20 | yarn-debug.log*
21 | yarn-error.log*
22 |
--------------------------------------------------------------------------------
/examples/lazy-read/README.md:
--------------------------------------------------------------------------------
1 | # Lazy Read
2 |
3 | This project template was built with [Create React App](https://github.com/facebookincubator/create-react-app), which provides a simple way to start React projects with no build configuration needed.
4 |
5 | Projects built with Create-React-App include support for ES6 syntax, as well as several unofficial / not-yet-final forms of Javascript syntax such as Class Properties and JSX. See the list of [language features and polyfills supported by Create-React-App](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#supported-language-features-and-polyfills) for more information.
6 |
7 | ## Available Scripts
8 |
9 | In the project directory, you can run:
10 |
11 | ### `npm start`
12 |
13 | Runs the app in the development mode.
14 | Open [http://localhost:3000](http://localhost:3000) to view it in the browser.
15 |
16 | The page will reload if you make edits.
17 | You will also see any lint errors in the console.
18 |
19 | ### `npm run build`
20 |
21 | Builds the app for production to the `build` folder.
22 | It correctly bundles React in production mode and optimizes the build for the best performance.
23 |
24 | The build is minified and the filenames include the hashes.
25 | Your app is ready to be deployed!
26 |
27 | ### `npm run eject`
28 |
29 | **Note: this is a one-way operation. Once you `eject`, you can’t go back!**
30 |
31 | If you aren’t satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project.
32 |
33 | Instead, it will copy all the configuration files and the transitive dependencies (Webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own.
34 |
35 | You don’t have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it.
36 |
--------------------------------------------------------------------------------
/examples/lazy-read/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "lazy-read",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "react": "^16.2.0",
7 | "react-dom": "^16.2.0",
8 | "react-request": "^3.0.0",
9 | "react-scripts": "1.1.0"
10 | },
11 | "scripts": {
12 | "start": "react-scripts start",
13 | "build": "react-scripts build",
14 | "test": "react-scripts test --env=jsdom",
15 | "eject": "react-scripts eject"
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/examples/lazy-read/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jamesplease/react-request/efda7bdcc083b9b956203ce6ef5eefadc6b36aa5/examples/lazy-read/public/favicon.ico
--------------------------------------------------------------------------------
/examples/lazy-read/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
11 |
12 |
13 |
22 | React App
23 |
24 |
25 |
28 |
29 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/examples/lazy-read/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "64x64 32x32 24x24 16x16",
8 | "type": "image/x-icon"
9 | }
10 | ],
11 | "start_url": "./index.html",
12 | "display": "standalone",
13 | "theme_color": "#000000",
14 | "background_color": "#ffffff"
15 | }
16 |
--------------------------------------------------------------------------------
/examples/lazy-read/src/App.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import { Fetch } from 'react-request';
3 |
4 | class App extends Component {
5 | render() {
6 | return (
7 |
8 | {({ fetching, failed, data, doFetch }) => (
9 |
10 |
13 | {fetching && 'Loading...'}
14 | {failed && 'There was some kind of error'}
15 | {data && (
16 |
17 |
Post title: {data.title}
18 |
Post ID: {data.id}
19 |
20 | )}
21 |
22 | )}
23 |
24 | );
25 | }
26 | }
27 |
28 | export default App;
29 |
--------------------------------------------------------------------------------
/examples/lazy-read/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import App from './App';
4 |
5 | ReactDOM.render(, document.getElementById('root'));
6 |
--------------------------------------------------------------------------------
/examples/multiple-requests/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 |
6 | # testing
7 | /coverage
8 |
9 | # production
10 | /build
11 |
12 | # misc
13 | .DS_Store
14 | .env.local
15 | .env.development.local
16 | .env.test.local
17 | .env.production.local
18 |
19 | npm-debug.log*
20 | yarn-debug.log*
21 | yarn-error.log*
22 |
--------------------------------------------------------------------------------
/examples/multiple-requests/README.md:
--------------------------------------------------------------------------------
1 | # Multiple Requests
2 |
3 | This project template was built with [Create React App](https://github.com/facebookincubator/create-react-app), which provides a simple way to start React projects with no build configuration needed.
4 |
5 | Projects built with Create-React-App include support for ES6 syntax, as well as several unofficial / not-yet-final forms of Javascript syntax such as Class Properties and JSX. See the list of [language features and polyfills supported by Create-React-App](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#supported-language-features-and-polyfills) for more information.
6 |
7 | ## Available Scripts
8 |
9 | In the project directory, you can run:
10 |
11 | ### `npm start`
12 |
13 | Runs the app in the development mode.
14 | Open [http://localhost:3000](http://localhost:3000) to view it in the browser.
15 |
16 | The page will reload if you make edits.
17 | You will also see any lint errors in the console.
18 |
19 | ### `npm run build`
20 |
21 | Builds the app for production to the `build` folder.
22 | It correctly bundles React in production mode and optimizes the build for the best performance.
23 |
24 | The build is minified and the filenames include the hashes.
25 | Your app is ready to be deployed!
26 |
27 | ### `npm run eject`
28 |
29 | **Note: this is a one-way operation. Once you `eject`, you can’t go back!**
30 |
31 | If you aren’t satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project.
32 |
33 | Instead, it will copy all the configuration files and the transitive dependencies (Webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own.
34 |
35 | You don’t have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it.
36 |
--------------------------------------------------------------------------------
/examples/multiple-requests/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "multiple-requests",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "react": "^16.2.0",
7 | "react-composer": "^4.1.0",
8 | "react-dom": "^16.2.0",
9 | "react-request": "^3.0.0",
10 | "react-scripts": "1.1.0"
11 | },
12 | "scripts": {
13 | "start": "react-scripts start",
14 | "build": "react-scripts build",
15 | "test": "react-scripts test --env=jsdom",
16 | "eject": "react-scripts eject"
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/examples/multiple-requests/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jamesplease/react-request/efda7bdcc083b9b956203ce6ef5eefadc6b36aa5/examples/multiple-requests/public/favicon.ico
--------------------------------------------------------------------------------
/examples/multiple-requests/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
11 |
12 |
13 |
22 | React App
23 |
24 |
25 |
28 |
29 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/examples/multiple-requests/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "64x64 32x32 24x24 16x16",
8 | "type": "image/x-icon"
9 | }
10 | ],
11 | "start_url": "./index.html",
12 | "display": "standalone",
13 | "theme_color": "#000000",
14 | "background_color": "#ffffff"
15 | }
16 |
--------------------------------------------------------------------------------
/examples/multiple-requests/src/App.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import Composer from 'react-composer';
3 | import { Fetch } from 'react-request';
4 |
5 | class App extends Component {
6 | render() {
7 | return (
8 | ,
11 | ,
12 | ,
16 | ]}>
17 | {([readPostOne, readPostTwo, deletePostOne]) => (
18 |
19 |
24 |
25 |
26 | {readPostOne.fetching && 'Fetching post 1...'}
27 | {!readPostOne.fetching && 'Not currently fetching post 1.'}
28 | {readPostTwo.fetching && 'Fetching post 2...'}
29 | {!readPostTwo.fetching && 'Not currently fetching post 2.'}
30 |
31 | )}
32 |
33 | );
34 | }
35 | }
36 |
37 | export default App;
38 |
--------------------------------------------------------------------------------
/examples/multiple-requests/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import App from './App';
4 |
5 | ReactDOM.render(, document.getElementById('root'));
6 |
--------------------------------------------------------------------------------
/examples/request-deduplication/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 |
6 | # testing
7 | /coverage
8 |
9 | # production
10 | /build
11 |
12 | # misc
13 | .DS_Store
14 | .env.local
15 | .env.development.local
16 | .env.test.local
17 | .env.production.local
18 |
19 | npm-debug.log*
20 | yarn-debug.log*
21 | yarn-error.log*
22 |
--------------------------------------------------------------------------------
/examples/request-deduplication/README.md:
--------------------------------------------------------------------------------
1 | # Request Deduplication
2 |
3 | This project template was built with [Create React App](https://github.com/facebookincubator/create-react-app), which provides a simple way to start React projects with no build configuration needed.
4 |
5 | Projects built with Create-React-App include support for ES6 syntax, as well as several unofficial / not-yet-final forms of Javascript syntax such as Class Properties and JSX. See the list of [language features and polyfills supported by Create-React-App](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#supported-language-features-and-polyfills) for more information.
6 |
7 | ## Available Scripts
8 |
9 | In the project directory, you can run:
10 |
11 | ### `npm start`
12 |
13 | Runs the app in the development mode.
14 | Open [http://localhost:3000](http://localhost:3000) to view it in the browser.
15 |
16 | The page will reload if you make edits.
17 | You will also see any lint errors in the console.
18 |
19 | ### `npm run build`
20 |
21 | Builds the app for production to the `build` folder.
22 | It correctly bundles React in production mode and optimizes the build for the best performance.
23 |
24 | The build is minified and the filenames include the hashes.
25 | Your app is ready to be deployed!
26 |
27 | ### `npm run eject`
28 |
29 | **Note: this is a one-way operation. Once you `eject`, you can’t go back!**
30 |
31 | If you aren’t satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project.
32 |
33 | Instead, it will copy all the configuration files and the transitive dependencies (Webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own.
34 |
35 | You don’t have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it.
36 |
--------------------------------------------------------------------------------
/examples/request-deduplication/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "request-deduplication",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "react": "^16.2.0",
7 | "react-dom": "^16.2.0",
8 | "react-request": "^3.0.0",
9 | "react-scripts": "1.1.0"
10 | },
11 | "scripts": {
12 | "start": "react-scripts start",
13 | "build": "react-scripts build",
14 | "test": "react-scripts test --env=jsdom",
15 | "eject": "react-scripts eject"
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/examples/request-deduplication/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jamesplease/react-request/efda7bdcc083b9b956203ce6ef5eefadc6b36aa5/examples/request-deduplication/public/favicon.ico
--------------------------------------------------------------------------------
/examples/request-deduplication/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
11 |
12 |
13 |
22 | React App
23 |
24 |
25 |
28 |
29 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/examples/request-deduplication/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "64x64 32x32 24x24 16x16",
8 | "type": "image/x-icon"
9 | }
10 | ],
11 | "start_url": "./index.html",
12 | "display": "standalone",
13 | "theme_color": "#000000",
14 | "background_color": "#ffffff"
15 | }
16 |
--------------------------------------------------------------------------------
/examples/request-deduplication/src/App.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import { Fetch } from 'react-request';
3 |
4 | const urlOne = 'https://jsonplaceholder.typicode.com/posts/1';
5 | const urlTwo = 'https://jsonplaceholder.typicode.com/posts/2';
6 |
7 | class App extends Component {
8 | render() {
9 | // Open DevTools to observe that only one request is made for each URL
10 | return (
11 |
25 | Open the Network tab within DevTools to see the number of requests
26 | that are sent off.
27 |
28 |
29 | );
30 | }
31 | }
32 |
33 | export default App;
34 |
--------------------------------------------------------------------------------
/examples/request-deduplication/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import App from './App';
4 |
5 | ReactDOM.render(, document.getElementById('root'));
6 |
--------------------------------------------------------------------------------
/examples/response-caching/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 |
6 | # testing
7 | /coverage
8 |
9 | # production
10 | /build
11 |
12 | # misc
13 | .DS_Store
14 | .env.local
15 | .env.development.local
16 | .env.test.local
17 | .env.production.local
18 |
19 | npm-debug.log*
20 | yarn-debug.log*
21 | yarn-error.log*
22 |
--------------------------------------------------------------------------------
/examples/response-caching/README.md:
--------------------------------------------------------------------------------
1 | # Response Caching
2 |
3 | This project template was built with [Create React App](https://github.com/facebookincubator/create-react-app), which provides a simple way to start React projects with no build configuration needed.
4 |
5 | Projects built with Create-React-App include support for ES6 syntax, as well as several unofficial / not-yet-final forms of Javascript syntax such as Class Properties and JSX. See the list of [language features and polyfills supported by Create-React-App](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#supported-language-features-and-polyfills) for more information.
6 |
7 | ## Available Scripts
8 |
9 | In the project directory, you can run:
10 |
11 | ### `npm start`
12 |
13 | Runs the app in the development mode.
14 | Open [http://localhost:3000](http://localhost:3000) to view it in the browser.
15 |
16 | The page will reload if you make edits.
17 | You will also see any lint errors in the console.
18 |
19 | ### `npm run build`
20 |
21 | Builds the app for production to the `build` folder.
22 | It correctly bundles React in production mode and optimizes the build for the best performance.
23 |
24 | The build is minified and the filenames include the hashes.
25 | Your app is ready to be deployed!
26 |
27 | ### `npm run eject`
28 |
29 | **Note: this is a one-way operation. Once you `eject`, you can’t go back!**
30 |
31 | If you aren’t satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project.
32 |
33 | Instead, it will copy all the configuration files and the transitive dependencies (Webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own.
34 |
35 | You don’t have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it.
36 |
--------------------------------------------------------------------------------
/examples/response-caching/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "response-caching",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "react": "^16.2.0",
7 | "react-dom": "^16.2.0",
8 | "react-request": "^3.0.0",
9 | "react-scripts": "1.1.0"
10 | },
11 | "scripts": {
12 | "start": "react-scripts start",
13 | "build": "react-scripts build",
14 | "test": "react-scripts test --env=jsdom",
15 | "eject": "react-scripts eject"
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/examples/response-caching/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jamesplease/react-request/efda7bdcc083b9b956203ce6ef5eefadc6b36aa5/examples/response-caching/public/favicon.ico
--------------------------------------------------------------------------------
/examples/response-caching/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
11 |
12 |
13 |
22 | React App
23 |
24 |
25 |
28 |
29 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/examples/response-caching/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "64x64 32x32 24x24 16x16",
8 | "type": "image/x-icon"
9 | }
10 | ],
11 | "start_url": "./index.html",
12 | "display": "standalone",
13 | "theme_color": "#000000",
14 | "background_color": "#ffffff"
15 | }
16 |
--------------------------------------------------------------------------------
/examples/response-caching/src/App.js:
--------------------------------------------------------------------------------
1 | import React, { Component, Fragment } from 'react';
2 | import { Fetch } from 'react-request';
3 | import { setTimeout } from 'timers';
4 |
5 | const url = 'https://jsonplaceholder.typicode.com/posts/1';
6 | let renderCount = 0;
7 |
8 | class App extends Component {
9 | render() {
10 | // Open DevTools to observe that only one request is made, even though two fetch components are mounted.
11 | // The second component receives the data that was cached after the first Fetch's response completes.
12 | return (
13 |
14 |
15 | {this.state.fetchAgain && (
16 |
17 | {stuff => {
18 | if (renderCount === 0) {
19 | console.log(
20 | 'The second fetch component just mounted. You should see that only one request was made in the network tab (unless your connection is really slow).',
21 | stuff
22 | );
23 |
24 | renderCount++;
25 | }
26 |
27 | return null;
28 | }}
29 |
30 | )}
31 |
Check out the DevTools console to interpret this example.
32 |
33 | );
34 | }
35 |
36 | state = {
37 | fetchAgain: false,
38 | };
39 |
40 | componentDidMount() {
41 | setTimeout(() => {
42 | this.setState({
43 | fetchAgain: true,
44 | });
45 | }, 2000);
46 | }
47 | }
48 |
49 | export default App;
50 |
--------------------------------------------------------------------------------
/examples/response-caching/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import App from './App';
4 |
5 | ReactDOM.render(, document.getElementById('root'));
6 |
--------------------------------------------------------------------------------
/examples/simple-read/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 |
6 | # testing
7 | /coverage
8 |
9 | # production
10 | /build
11 |
12 | # misc
13 | .DS_Store
14 | .env.local
15 | .env.development.local
16 | .env.test.local
17 | .env.production.local
18 |
19 | npm-debug.log*
20 | yarn-debug.log*
21 | yarn-error.log*
22 |
--------------------------------------------------------------------------------
/examples/simple-read/README.md:
--------------------------------------------------------------------------------
1 | # Simple Read
2 |
3 | This project template was built with [Create React App](https://github.com/facebookincubator/create-react-app), which provides a simple way to start React projects with no build configuration needed.
4 |
5 | Projects built with Create-React-App include support for ES6 syntax, as well as several unofficial / not-yet-final forms of Javascript syntax such as Class Properties and JSX. See the list of [language features and polyfills supported by Create-React-App](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#supported-language-features-and-polyfills) for more information.
6 |
7 | ## Available Scripts
8 |
9 | In the project directory, you can run:
10 |
11 | ### `npm start`
12 |
13 | Runs the app in the development mode.
14 | Open [http://localhost:3000](http://localhost:3000) to view it in the browser.
15 |
16 | The page will reload if you make edits.
17 | You will also see any lint errors in the console.
18 |
19 | ### `npm run build`
20 |
21 | Builds the app for production to the `build` folder.
22 | It correctly bundles React in production mode and optimizes the build for the best performance.
23 |
24 | The build is minified and the filenames include the hashes.
25 | Your app is ready to be deployed!
26 |
27 | ### `npm run eject`
28 |
29 | **Note: this is a one-way operation. Once you `eject`, you can’t go back!**
30 |
31 | If you aren’t satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project.
32 |
33 | Instead, it will copy all the configuration files and the transitive dependencies (Webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own.
34 |
35 | You don’t have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it.
36 |
--------------------------------------------------------------------------------
/examples/simple-read/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "simple-read",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "react": "^16.2.0",
7 | "react-dom": "^16.2.0",
8 | "react-request": "^3.0.0",
9 | "react-scripts": "1.1.0"
10 | },
11 | "scripts": {
12 | "start": "react-scripts start",
13 | "build": "react-scripts build",
14 | "test": "react-scripts test --env=jsdom",
15 | "eject": "react-scripts eject"
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/examples/simple-read/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jamesplease/react-request/efda7bdcc083b9b956203ce6ef5eefadc6b36aa5/examples/simple-read/public/favicon.ico
--------------------------------------------------------------------------------
/examples/simple-read/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
11 |
12 |
13 |
22 | React App
23 |
24 |
25 |
28 |
29 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/examples/simple-read/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "64x64 32x32 24x24 16x16",
8 | "type": "image/x-icon"
9 | }
10 | ],
11 | "start_url": "./index.html",
12 | "display": "standalone",
13 | "theme_color": "#000000",
14 | "background_color": "#ffffff"
15 | }
16 |
--------------------------------------------------------------------------------
/examples/simple-read/src/App.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import { Fetch } from 'react-request';
3 |
4 | class App extends Component {
5 | render() {
6 | return (
7 |
8 | {({ fetching, failed, data }) => (
9 |
10 | {fetching && 'Loading...'}
11 | {failed && 'There was some kind of error'}
12 | {data && (
13 |
14 |
Post title: {data.title}
15 |
Post ID: {data.id}
16 |
17 | )}
18 |
19 | )}
20 |
21 | );
22 | }
23 | }
24 |
25 | export default App;
26 |
--------------------------------------------------------------------------------
/examples/simple-read/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import App from './App';
4 |
5 | ReactDOM.render(, document.getElementById('root'));
6 |
--------------------------------------------------------------------------------
/examples/updating-a-resource/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 |
6 | # testing
7 | /coverage
8 |
9 | # production
10 | /build
11 |
12 | # misc
13 | .DS_Store
14 | .env.local
15 | .env.development.local
16 | .env.test.local
17 | .env.production.local
18 |
19 | npm-debug.log*
20 | yarn-debug.log*
21 | yarn-error.log*
22 |
--------------------------------------------------------------------------------
/examples/updating-a-resource/README.md:
--------------------------------------------------------------------------------
1 | # Updating a Resource
2 |
3 | This project template was built with [Create React App](https://github.com/facebookincubator/create-react-app), which provides a simple way to start React projects with no build configuration needed.
4 |
5 | Projects built with Create-React-App include support for ES6 syntax, as well as several unofficial / not-yet-final forms of Javascript syntax such as Class Properties and JSX. See the list of [language features and polyfills supported by Create-React-App](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#supported-language-features-and-polyfills) for more information.
6 |
7 | ## Available Scripts
8 |
9 | In the project directory, you can run:
10 |
11 | ### `npm start`
12 |
13 | Runs the app in the development mode.
14 | Open [http://localhost:3000](http://localhost:3000) to view it in the browser.
15 |
16 | The page will reload if you make edits.
17 | You will also see any lint errors in the console.
18 |
19 | ### `npm run build`
20 |
21 | Builds the app for production to the `build` folder.
22 | It correctly bundles React in production mode and optimizes the build for the best performance.
23 |
24 | The build is minified and the filenames include the hashes.
25 | Your app is ready to be deployed!
26 |
27 | ### `npm run eject`
28 |
29 | **Note: this is a one-way operation. Once you `eject`, you can’t go back!**
30 |
31 | If you aren’t satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project.
32 |
33 | Instead, it will copy all the configuration files and the transitive dependencies (Webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own.
34 |
35 | You don’t have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it.
36 |
--------------------------------------------------------------------------------
/examples/updating-a-resource/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "updating-a-resource",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "react": "^16.2.0",
7 | "react-dom": "^16.2.0",
8 | "react-request": "^3.0.0",
9 | "react-scripts": "1.1.0"
10 | },
11 | "scripts": {
12 | "start": "react-scripts start",
13 | "build": "react-scripts build",
14 | "test": "react-scripts test --env=jsdom",
15 | "eject": "react-scripts eject"
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/examples/updating-a-resource/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jamesplease/react-request/efda7bdcc083b9b956203ce6ef5eefadc6b36aa5/examples/updating-a-resource/public/favicon.ico
--------------------------------------------------------------------------------
/examples/updating-a-resource/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
11 |
12 |
13 |
22 | React App
23 |
24 |
25 |
28 |
29 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/examples/updating-a-resource/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "64x64 32x32 24x24 16x16",
8 | "type": "image/x-icon"
9 | }
10 | ],
11 | "start_url": "./index.html",
12 | "display": "standalone",
13 | "theme_color": "#000000",
14 | "background_color": "#ffffff"
15 | }
16 |
--------------------------------------------------------------------------------
/examples/updating-a-resource/src/App.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import { Fetch } from 'react-request';
3 |
4 | class App extends Component {
5 | render() {
6 | return (
7 |
8 | {({ fetching, failed, doFetch }) => (
9 |
10 |
25 | {fetching && 'Saving post 1...'}
26 | {failed && 'There was some kind of error'}
27 |