This package is a simple solution for handling actions or requests with redux while the app is in an offline state by queueing these, and dispatching them once connectivity is re-established. Works perfect with react-native
Motivation: Provide a better user experience.
yarn add redux-offline-queue
OR (old school)
npm install --save redux-offline-queue
See example project here: offlineTweet
Get up and running in 4 easy steps:
Either import the { reducer as offline }
from redux-offline-queue
and add it to the combineReducers
or require it like so (whatever floats your boat):
import { combineReducers } from 'redux'
export default combineReducers({
offline: require('redux-offline-queue').reducer,
yourOtherReducer: require('~App/yourOtherReducer').reducer,
})
import { offlineMiddleware } from 'redux-offline-queue'
const composeStoreWithMiddleware = applyMiddleware(
offlineMiddleware()
)(createStore)
Note that this queue is not persisted by itself. One should provide a persistence config by using e.g. redux-persist
to keep the offline queue persisted.
reduxsauce
import { createReducer, createActions } from 'reduxsauce'
import { markActionsOffline } from 'redux-offline-queue'
const { Types, Creators } = createActions({
requestBlogs: null,
createBlog: ['blog'],
})
markActionsOffline(Creators, ['createBlog'])
...
import { markActionsOffline } from 'redux-offline-queue'
const Creators = {
createBlog: blog => ({
type: 'CREATE_BLOG',
blog,
}),
}
markActionsOffline(Creators, ['createBlog'])
...
Last but not least...
import { OFFLINE, ONLINE } from 'redux-offline-queue'
if (appIsConnected) {
dispatch({ type: ONLINE })
} else {
dispatch({ type: OFFLINE })
}
Works perfect with React Native's NetInfo
import { put, take, call } from 'redux-saga/effects'
import NetInfo from '@react-native-community/netinfo'
import { OFFLINE, ONLINE } from 'redux-offline-queue'
function* startWatchingNetworkConnectivity() {
const channel = eventChannel((emitter) => {
NetInfo.isConnected.addEventListener('connectionChange', emitter)
return () => NetInfo.isConnected.removeEventListener('connectionChange', emitter)
})
try {
while(true) {
const isConnected = yield take(channel)
if (isConnected) {
yield put({ type: ONLINE })
} else {
yield put({ type: OFFLINE })
}
}
} finally {
channel.close()
}
}
Android
If react native's NetInfo
is intended to be used, for android don't forget to add the following to the AndroidManifest.xml
:
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
Inspired by redux-queue-offline(mathieudutour)
Developed by Krzysztof Ciombor
redux-saga
If you are using redux-sagas
for http requests and want to fire your redux actions normally, but suspend(queue) sagas, for Step 2, do the following instead:
import { applyMiddleware } from 'redux'
import createSagaMiddleware from 'redux-saga'
import {
offlineMiddleware,
suspendSaga,
consumeActionMiddleware,
} from 'redux-offline-queue'
const middleware = []
middleware.push(offlineMiddleware())
const suspendSagaMiddleware = suspendSaga(createSagaMiddleware())
middleware.push(suspendSagaMiddleware)
middleware.push(consumeActionMiddleware())
applyMiddleware(...middleware)
It is IMPORTANT that the consumeActionMiddleware
is placed last, so you can allow the previous middlewares to react first before eventually getting consumed.
Additional configuration can be passed with offlineMiddleware()
, such as adding additional triggers that will trigger the offline queue to dispatch its actions:
...
import { REHYDRATE } from 'redux-persist'
applyMiddleware(offlineMiddleware({
additionalTriggers: REHYDRATE,
}))
...
Bug reports and pull requests are welcome. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the Contributor Covenant code of conduct.
Original work copyright 2018-2019 Inspire Innovation BV. Continued work copyright 2019 Roberto Pando.
Read LICENSE for details.
The development of this package has been sponsored by Inspire Innovation BV (Utrecht, The Netherlands).