From c4b6f2cb6fa04de52be6c337f11dd993650f7a35 Mon Sep 17 00:00:00 2001 From: nodkz Date: Sat, 3 Mar 2018 14:15:08 +0600 Subject: [PATCH] feat: add `beforeFetch` option to `RelayNetworkLayer(middlewares, { beforeFetch })`. BREAKING CHANGE: If you use subscriptions in your app and provide `subscribeFn` as a second argument for RelayNetworkLayer. Now you should to provide it as a named option: ```new RelayNetworkLayer(middlewares, { subscribeFn: ...fn.code... });`. --- README.md | 15 ++++++++++++++- src/RelayNetworkLayer.js | 24 ++++++++++++++++++++---- src/definition.js | 6 ++++++ 3 files changed, 40 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 25d3838..1028b23 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,8 @@ with various middlewares which can manipulate requests/responses on the fly (cha Network Layer for Relay Classic can be found [here](https://github.com/nodkz/react-relay-network-layer). +Migration guide from v1 to v2 can be found [here](https://github.com/nodkz/react-relay-network-modern/releases/tag/v2.0.0). + `ReactRelayNetworkModern` can be used in browser, react-native or node server for rendering. Under the hood this module uses global `fetch` method. So if your client is too old, please import explicitly proper polyfill to your code (eg. `whatwg-fetch`, `node-fetch` or `fetch-everywhere`). Install @@ -166,13 +168,24 @@ const network = new RelayNetworkLayer([ return res; } -]); // as second arg you may pass SubscribeFunction +], opts); // as second arg you may pass advanced options for RRNL const source = new RecordSource(); const store = new Store(source); const environment = new Environment({ network, store }); ``` +### Advanced options (2nd argument after middlewares) +RelayNetworkLayer may accept additional options: +```js +const middlewares = []; // array of middlewares +const options = {}; // optional advanced options +const network = new RelayNetworkLayer(middlewares, options); +``` +Available options: +- **subscribeFn** - if you use subscriptions in your app, you may provide this function which will be passed to [RelayNetwork](https://github.com/facebook/relay/blob/master/packages/relay-runtime/network/RelayNetwork.js). +- **beforeFetch** - if you need synchronously render app on the client side from already generated payload by server (SSR) this options is for you. Some details can be found [here](https://github.com/facebook/relay/issues/2232). + ### Server-side rendering (SSR) For performant server-side rendering with `node 8` and above recommended to use special build of this network layer. Also you may execute `graphql` directly without http-request if you write custom middleware. All this recommendations present in following example: diff --git a/src/RelayNetworkLayer.js b/src/RelayNetworkLayer.js index 69282d6..e3b0356 100644 --- a/src/RelayNetworkLayer.js +++ b/src/RelayNetworkLayer.js @@ -6,21 +6,37 @@ import fetchWithMiddleware from './fetchWithMiddleware'; import type { Middleware, FetchFunction, + FetchHookFunction, SubscribeFunction, RNLExecuteFunction, } from './definition'; +type RelayNetworkLayerOpts = {| + subscribeFn?: SubscribeFunction, + beforeFetch?: FetchHookFunction, +|}; + export default class RelayNetworkLayer { _middlewares: Middleware[]; execute: RNLExecuteFunction; - fetchFn: FetchFunction; - subscribeFn: ?SubscribeFunction; + +fetchFn: FetchFunction; + +subscribeFn: ?SubscribeFunction; + beforeFetch: ?FetchHookFunction; - constructor(middlewares: Array, subscribeFn?: SubscribeFunction) { + constructor(middlewares: Array, opts?: RelayNetworkLayerOpts) { this._middlewares = Array.isArray(middlewares) ? (middlewares: any) : [middlewares]; - this.subscribeFn = subscribeFn; + + if (opts) { + this.subscribeFn = opts.subscribeFn; + this.beforeFetch = opts.beforeFetch; + } this.fetchFn = (operation, variables, cacheConfig, uploadables) => { + if (this.beforeFetch) { + const res = this.beforeFetch(operation, variables, cacheConfig, uploadables); + if (res) return res; + } + const req = new RelayRequest(operation, variables, cacheConfig, uploadables); return fetchWithMiddleware(req, this._middlewares.filter(o => !!o)); }; diff --git a/src/definition.js b/src/definition.js index 9dc408c..ba23fe5 100644 --- a/src/definition.js +++ b/src/definition.js @@ -95,6 +95,12 @@ export type FetchFunction = ( cacheConfig: CacheConfig, uploadables: ?UploadableMap ) => ObservableFromValue; +export type FetchHookFunction = ( + operation: ConcreteBatch, + variables: Variables, + cacheConfig: CacheConfig, + uploadables: ?UploadableMap +) => void | ObservableFromValue; // See SubscribeFunction type declaration in relay-runtime/network/RelayNetworkTypes.js export type SubscribeFunction = ( operation: ConcreteBatch,