handleRequests

As you probably noticed in other chapters, handleRequests is a function which gets some options and returns an object with all the pieces necessary to pass to redux, like requestsReducer etc.

handleRequest response object

handleRequests response object contains the following keys:

requestsReducer

Ready to use reducer managing the whole remote state, you need to attach it to requests key in combineReducers.

requestsMiddleware

A list of middleware you should pass to applyMiddleware. This list is dynamic and depends on other options, like cache and ssr.

requestsPromise

A promise which is resolved after all requests are finished, only with ssr: 'server' option.

handleRequest options

driver

The only option which is required, a driver or object of drivers if you use multiple drivers.

onRequest: (request, requestAction, store) => request

Function which will be called before request is made. It can be used to make some side effects, for example with store.dispatch or to update request config by returning an updated one. See interceptors tutorial.

onSuccess: (response, requestAction, store) => response

Function which will be called after successful response but before success action is dispatched. It can be used to make some side effects or to update response by returning another one. See interceptors tutorial.

onError: (error, requestAction, store) => error

Function which will be called after error response but before error action is dispatched. It can be used to make some side effects or to update error by throwing another one. It is also possible to recover from error by returning a response. See interceptors tutorial.

onAbort: (requestAction, store) => void

Function which will be called after abort but before abort action is dispatched. Usually it won't be useful, but it is available just in case. See interceptors tutorial.

cache: boolean

Set to true if you need to use caching. See caching tutorial for more info.

ssr: 'client' | 'server'

Pass server on the server and client on the client to activate server side rendering support. See server side rendering guide.

disableRequestsPromise: boolean

It only matters when ssr: 'server', you can set it to true if you don't need to be notified by requestsPromise when all requests were resolved. Typically you would set it to true when using React SSR suspense, false by default.

isRequestAction: action => boolean

Here you can adjust which actions are treated as request actions, usually you don't need to worry about it, it might be useful for custom drivers.

isRequestActionQuery: requestAction => boolean

If this function returns true, request action is treated as query, if false, as mutation, probably only useful for custom drivers.

takeLatest: boolean || requestAction => boolean

When true, if a request of a given type is pending and another one is fired, the first one will be automatically aborted, which can prevent race condition bugs and improve performance, default as true for queries and false for mutations, which is usually what you want. See abort tutorial for more info.

normalize: boolean

By default false, pass true to turn on normalisation for all requests. See automatic normalisation tutorial for more info.

getNormalisationObjectKey: obj => string

obj => obj.id by default, useful only if you use normalisation. See automatic normalisation tutorial for more info.

shouldObjectBeNormalized: obj => string

obj => obj.id !== undefined by default, useful only if you use normalisation. See automatic normalisation tutorial for more info.

subscriber

Only if you have a websocket server to connect to and you want to use subscriptions. It is an object with the following attributes:

url: string

The only required attribute. It is just an address of your websocket server, for example ws://localhost:3000/ws

protocols: string | string[]

Only if your websocket server requires it. It will be passed as 2nd argument to WebSocket constructor.

WS

Pass if you want to use your own WebSocket constructor. By default window.WebSocket is used.

onOpen: (store, ws, props) => void

A function executed when a new websocket connection is established. For example you can dispatch some actions or send a message to websocket server:

(store, ws, props) => {
store.dispatch(someAction(props));
ws.send(
JSON.stringify({
type: 'messageOnStart',
props,
}),
);
};

Props are available, if they were passed in openWebsocket action.

onClose: (e, store, ws) => void

A function executed when a websocket connection is closed. For example:

(e, store, ws) => {
store.dispatch(someAction());
};

onError: (e, store, ws) => void

A function executed on a websocket error. For example:

(e, store, ws) => {
store.dispatch(someAction());
};

onMessage: (data, message, store) => void

A function which will be called on each received message from the server. It can be used for side-effects.

onSend: (message, subscriptionAction) => any

It allows you to globally intercept and transform all subscription messages sent to websocket server. For example:

(message, subscriptionAction) => {
return {
type: 'start',
payload: message,
};
};

activateOn: message => boolean

Useful, if you websocket server needs to confirm that connection is opened correctly, for example that the connection was properly authenticated. For instance:

message => {
const data = JSON.parse(message.data);
return data.type === 'connection_confirmed';
};

When used, only after a message from the server, which confirms the connection, the connection will be considered as opened.

getData: data => any

It allows to transform messages reveived from websocket server. Useful especially because this library uses a convenction to match server messages and subscription actions by type. For example a message { type: 'ON_BOOK_ADDED', bookId: '1' } will match a subscription with type: 'ON_BOOK_ADDED'. But what if the server message structure is different? For example { id: 'ON_BOOK_ADDED', payload: { bookId: '1' } }? Then, you could do something like that:

data => {
if (data.id && data.payload) {
return { type: data.id, ...data.payload };
}
return data;
};

onStopSubscriptions: (stoppedSubscriptions, action, ws, store) => void

Perhaps you websocket server requires a message from the client to stop a subscription. When you dispatch stopSubscriptions action, still those actions would be ignored by the client, however it is a waste for the server to send messages which would be ignored anyway. Here you can see an example from graphql subscriptions:

(stoppedSubscriptions, action, ws) => {
if (!ws) {
return;
}
stoppedSubscriptions.forEach(subscription => {
ws.send(JSON.stringify({ type: 'stop', id: subscription }));
});
};

lazy: boolean

If false, then the client will be automatically connected to the websocket server. Pass true, if you prefer to connect manually by dispatching openWebsocket action. Typically true is needed, if you need to pass some extra props to openWebsocket action, false by default.

isHeartbeatMessage: message => boolean

Using heartbeats is a nice way to detect when websocket connection is interrupted in a reliable way. If your websocket server supports heartbeats, you can provide a function to detect them. For instance:

message => {
const data = JSON.parse(message.data);
return data.type === 'heartbeat';
};

heartbeatTimeout: number

Only if isHeartbeatMessage is defined. Length of a period in seconds, within which the client must receive a heartbeat message from the server. If not, websocket will be automatically closed. Then, if reconnectTimeout is defined, the client will try to automatically reconnect. 20 by default.

reconnectTimeout: number

Number of seconds, after which the client will try to reconnect after websocket connection has been closed uncleanly. 5 by default. Pass null if you prefer to disable automatic reconnections.

Last updated on by klis87