From 49d812d1c31f3fbbf91591e07e031c5b2d2e01c7 Mon Sep 17 00:00:00 2001 From: Jmeas Date: Sat, 20 Jan 2018 10:20:52 -0800 Subject: [PATCH 1/6] Compute laziness based on method --- src/request.js | 40 ++++++++++++++++++++++++++++++++-------- 1 file changed, 32 insertions(+), 8 deletions(-) diff --git a/src/request.js b/src/request.js index dc83a63..f12e52b 100644 --- a/src/request.js +++ b/src/request.js @@ -32,16 +32,41 @@ export default class Request extends React.Component { } } - state = { - requestName: this.props.requestName, - fetching: !this.props.lazy, - response: null, - data: null, - error: null + constructor(props, context) { + super(props, context); + + this.state = { + requestName: props.requestName, + fetching: !this.isLazy(), + response: null, + data: null, + error: null + }; + } + + isLazy = props => { + const { lazy, method } = props || this.props; + + const uppercaseMethod = method.toUpperCase(); + + let laziness; + + // We default to being lazy for "write" requests, + // such as POST, PATCH, DELETE, and so on. + if (typeof lazy === 'undefined') { + laziness = + uppercaseMethod !== 'GET' && + uppercaseMethod !== 'HEAD' && + uppercaseMethod !== 'OPTIONS'; + } else { + laziness = lazy; + } + + return laziness; }; componentDidMount() { - if (!this.props.lazy) { + if (!this.isLazy()) { this.fetchData(); } } @@ -228,7 +253,6 @@ Request.defaultProps = { onResponse: () => {}, transformResponse: data => data, fetchPolicy: 'cache-first', - lazy: false, method: 'get', referrerPolicy: '', From 61c6b09be8aec9e90f3ab4c66b4235ad9342a12a Mon Sep 17 00:00:00 2001 From: Jmeas Date: Sat, 20 Jan 2018 10:24:49 -0800 Subject: [PATCH 2/6] Rename Request component to be Fetch --- README.md | 19 +++++++------------ ...{request-composer.js => fetch-composer.js} | 4 ++-- src/{request.js => fetch.js} | 6 +++--- src/index.js | 6 +++--- test/index.test.js | 4 ++-- 5 files changed, 17 insertions(+), 22 deletions(-) rename src/{request-composer.js => fetch-composer.js} (94%) rename src/{request.js => fetch.js} (98%) diff --git a/README.md b/README.md index 87fbca0..9a93a19 100644 --- a/README.md +++ b/README.md @@ -40,12 +40,12 @@ yarn add react-request Here's a simple example of using React Request. ```js -import { Request } from 'react-request'; +import { Fetch } from 'react-request'; class App extends Component { render() { return ( - { if (fetching) { @@ -69,24 +69,19 @@ class App extends Component { } ``` -> Note: the name given to this library in the above example will shadow the -> [`Request`](https://developer.mozilla.org/en-US/docs/Web/API/Request/Request) -> constructor. Most people do not use the Request constructor directly, but if -> you prefer it you can use another name, such as `Req`, instead. - Need to make multiple requests? We got you. ```js -import { RequestComposer } from 'react-request'; +import { FetchComposer } from 'react-request'; class App extends Component { render() { return ( - , - , - + , + , + ]} render={([postOne, postTwo, postThree]) => { return ( diff --git a/src/request-composer.js b/src/fetch-composer.js similarity index 94% rename from src/request-composer.js rename to src/fetch-composer.js index 3a060ce..33124ce 100644 --- a/src/request-composer.js +++ b/src/fetch-composer.js @@ -1,7 +1,7 @@ import React from 'react'; import PropTypes from 'prop-types'; -export default function RequestComposer({ requests = [], render }) { +export default function FetchComposer({ requests = [], render }) { if (typeof render !== 'function') { return null; } @@ -47,7 +47,7 @@ export default function RequestComposer({ requests = [], render }) { return chainRequests(reversedRequests); } -RequestComposer.propTypes = { +FetchComposer.propTypes = { render: PropTypes.func, requests: PropTypes.array }; diff --git a/src/request.js b/src/fetch.js similarity index 98% rename from src/request.js rename to src/fetch.js index f12e52b..0f1b166 100644 --- a/src/request.js +++ b/src/fetch.js @@ -11,7 +11,7 @@ function getRequestKey({ url, method, type, body }) { return [url, method, type, body].join('||'); } -export default class Request extends React.Component { +export default class Fetch extends React.Component { render() { const { render, requestName } = this.props; const { fetching, response, data, error } = this.state; @@ -184,7 +184,7 @@ export default class Request extends React.Component { const globalObj = typeof self !== 'undefined' ? self : this; const AbortSignalCtr = globalObj.AbortSignal || function() {}; -Request.propTypes = { +Fetch.propTypes = { requestName: PropTypes.string, children: PropTypes.func, fetchPolicy: PropTypes.oneOf([ @@ -248,7 +248,7 @@ Request.propTypes = { signal: PropTypes.instanceOf(AbortSignalCtr) }; -Request.defaultProps = { +Fetch.defaultProps = { type: 'json', onResponse: () => {}, transformResponse: data => data, diff --git a/src/index.js b/src/index.js index bf4b653..a3fb7fb 100644 --- a/src/index.js +++ b/src/index.js @@ -1,4 +1,4 @@ -import Request from './request'; -import RequestComposer from './request-composer'; +import Fetch from './fetch'; +import FetchComposer from './fetch-composer'; -export { Request, RequestComposer }; +export { Fetch, FetchComposer }; diff --git a/test/index.test.js b/test/index.test.js index 9e5a867..d160ee4 100644 --- a/test/index.test.js +++ b/test/index.test.js @@ -1,5 +1,5 @@ -import { Request } from '../src'; +import { Fetch } from '../src'; test('Placeholder test', () => { - expect(Request).toBeTruthy(); + expect(Fetch).toBeTruthy(); }); From 29af5907b98a800df9ed9b2dd4e57a7c3aaf1a94 Mon Sep 17 00:00:00 2001 From: Jmeas Date: Sat, 20 Jan 2018 11:01:50 -0800 Subject: [PATCH 3/6] Update API; add API guide for Fetch --- README.md | 154 +++++++++++++++++++++++++++++++++++++++++- src/fetch-composer.js | 1 - src/fetch-dedupe.js | 4 +- src/fetch.js | 23 ++++--- 4 files changed, 169 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 9a93a19..bfadc27 100644 --- a/README.md +++ b/README.md @@ -112,7 +112,159 @@ Check out the API reference below for more. ### API -Documentation coming soon. +This library has two exports: + +* `Fetch`: +* `FetchComposer`: A component for making parallel HTTP requests + +#### `` + +A component for making a single HTTP request. It accepts every value of `init` and `input` +from the `fetch()` API as a prop, in addition to a few other things. + +Props from the `fetch()` method are: + +* `url` +* `method`: defaults to `"GET"` +* `body` +* `credentials` +* `headers` +* `mode` +* `cache` +* `redirect` +* `referrer`: defaults to `"about:client"` +* `referrerPolicy`: defaults to `""` +* `integrity`: defaults to `""` +* `keepalive` +* `signal` + +To learn more about the valid options for these props, refer to the +[`fetch()`](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch) +documentation. + +An example demonstrating some common values is: + +```jsx + { + ; }} /> ``` -In addition to the `fetch()` props, there are a handful of other props. - -##### `contentType` - -The content type of the response body. Defaults to `json`. Valid options are the methods -on [Body](https://developer.mozilla.org/en-US/docs/Web/API/Body). +In addition to the `fetch()` props, there are a number of other useful props. ##### `render` -The "render prop" of this component. It is called with one argument, `result`, an object -with the following keys: +The [render prop](https://cdb.reacttraining.com/use-a-render-prop-50de598f11ce) of this component. +It is called with one argument, `result`, an object with the following keys: * `fetching`: A Boolean representing whether or not a request is currently in flight for this component * `error`: A Boolean representing if a network error occurred. Note that HTTP "error" status codes do not cause `error` to be `true`; only failed or aborted network requests do. * `response`: An instance of [Response](https://developer.mozilla.org/en-US/docs/Web/API/Response). The - `body` will already be read, and made available to you via `response.data`. + `body` will already be read, and made available to you as `response.data`. * `data`: An alias of `response.data` * `fetch`: A function that makes the HTTP request. See notes below. * `requestName`: The name of the request (see `requestName` below) @@ -197,10 +192,10 @@ There are three common use cases for the `fetch` prop: Whether or not the request will be called when the component mounts. The default value is based on the request method that you use. -| Method | Default value | -| ------------------- | ------------- | -| GET, HEAD, OPTIONS | `false` | -| POST, PATCH, DELETE | `true` | +| Method | Default value | +| ------------------------ | ------------- | +| GET, HEAD, OPTIONS | `false` | +| POST, PUT, PATCH, DELETE | `true` | ##### `onResponse` @@ -240,7 +235,7 @@ hook to transform the data before it is passed into `render`. {!fetching && !error && response.status === 200 && (

{data.title}

-
{data.content} +
{data.content}
)}
@@ -248,9 +243,14 @@ hook to transform the data before it is passed into `render`. /> ``` +##### `contentType` + +The content type of the response body. Defaults to `json`. Valid values are the methods +on [Body](https://developer.mozilla.org/en-US/docs/Web/API/Body). + ##### `requestName` -A name to give this request which can help with debugging purposes. The request name is +A name to give this request, which can help with debugging purposes. The request name is analogous to a function name in JavaScript. Although we could use anonymous functions everywhere, we tend to give them names to help humans read and debug the code. @@ -266,6 +266,8 @@ This prop is identical to the Apollo prop. (The API will be listed here shortly). +--- + #### `` A component that simplifies making parallel requests.