Permalink
Browse files

WIP - Thunks in Prod bug fix (#27)

Fixes #26 

* Prettier + Flow

* fix: thunks in production intercepted

* Update README.md

Reflecting API changes for Thunks

* Version bump
  • Loading branch information...
Raúl Gómez Acuña
Raúl Gómez Acuña committed Jul 31, 2017
1 parent bf36067 commit 2a27c6c2d4347f8e5d75d91dde7feb7ab5766ea1
View
@@ -28,16 +28,36 @@
"browser": true // This is necessary for React Native fetch, see https://github.com/eslint/eslint/issues/4015
},
"rules": {
"prettier/prettier": [
"error",
{
"trailingComma": "all",
"singleQuote": true
}
],
"import/extensions": 0,
"no-use-before-define": 0,
"import/no-extraneous-dependencies": 0,
"global-require": 0,
"react/prop-types": 0,
"react/jsx-filename-extension": [1, { "extensions": [".js", ".jsx"] }],
"react/require-default-props": 0,
"prettier/prettier": [2, {
"singleQuote": true
}]
"flowtype/boolean-style": [
2,
"boolean"
],
"flowtype/no-weak-types": 1,
"flowtype/require-parameter-type": 2,
"flowtype/require-return-type": [
0,
"always",
{
"annotateUndefined": "never"
}
],
"flowtype/require-valid-file-annotation": 2,
"flowtype/use-flow-type": 1,
"flowtype/valid-syntax": 1
},
"globals": {
"jest": true
View
@@ -211,20 +211,29 @@ createNetworkMiddleware(config: Config): ReduxMiddleware
type Config = {
regexActionType?: RegExp = /FETCH.*REQUEST/,
regexFunctionName?: RegExp = /fetch/,
actionTypes?: Array<string> = []
}
```
##### Config
##### PO Config
This is the setup you need to put in place for libraries such as `redux-saga` or `redux-observable`, which rely on plain actions being dispatched to trigger async flow:
`regexActionType`: regular expression to indicate the action types to be intercepted in offline mode.
By default it's configured to intercept actions for fetching data following the Redux [convention](http://redux.js.org/docs/advanced/AsyncActions.html). That means that it will intercept actions with types such as `FETCH_USER_ID_REQUEST`, `FETCH_PRODUCTS_REQUEST` etc.
`regexFunctionName`: only for redux-thunk, regular expression for specifying the function names you are interested to catch in offline mode. Keep in mind that **it refers to the function returned by your action creator, not the action creator itself, so make sure to use a named function instead of an anonymous arrow function**. It defaults to function names that contains the string "fetch", such as `fetchData`. See the snippet below as reference.
`actionTypes`: array with additional action types to intercept that don't fulfil the RegExp criteria. For instance, it's useful for actions that carry along refreshing data, such as `REFRESH_LIST`.
##### Thunks Config
For `redux-thunk` library, the async flow is wrapped inside functions that will be lazily evaluated when dispatched, so our store is able to dispatch functions as well. Therefore, the configuration differs:
- Make sure to use a named function instead of an anonymous arrow function for the thunk returned by your action creator.
- Use `interceptInOffline` property in your thunk and set it to `true`.
Example:
```javascript
export const fetchUser = (url) => {
return function fetchData(dispatch) { // Name this function accordingly
return function thunk(dispatch) {
fetch(url)
.then((response) => response.json())
.then((responseJson) => {
@@ -234,11 +243,11 @@ export const fetchUser = (url) => {
console.error(error);
});
};
thunk.interceptInOffline = true; // This is the important part
};
```
`actionTypes`: array with additional action types to intercept that don't fulfil the RegExp criteria. For instance, it's useful for actions that carry along refreshing data, such as `REFRESH_LIST`.
##### Usage
You should apply the middleware to the store using `applyMiddleware`. **The network middleware should be the first on the chain**, before any other middleware used for handling async actions, such as [redux-thunk](https://github.com/gaearon/redux-thunk), [redux-saga](https://github.com/redux-saga/redux-saga) or [redux-observable](https://github.com/redux-observable/redux-observable).
View
@@ -11,4 +11,5 @@ dependencies:
- yarn install
test:
override:
- yarn run test
- yarn run flow
- yarn run jest:coverage
View
@@ -1,16 +1,19 @@
{
"name": "react-native-offline",
"version": "3.0.1",
"version": "3.1.0",
"description": "Handy toolbelt to deal with offline mode in React Native applications. Cross-platform, provides a smooth redux integration.",
"main": "./src/index.js",
"author": "Raul Gomez Acuña <raulgdeveloper@gmail.com> (https://github.com/rauliyohmc)",
"license": "MIT",
"scripts": {
"lint": "eslint .",
"lint": "eslint src",
"jest": "jest",
"test": "concurrently \"npm run lint\" \"npm run jest:coverage\" \"npm run flow\"",
"flow": "flow",
"jest:coverage": "node --harmony_proxies node_modules/.bin/jest --coverage && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js"
"format": "eslint --fix js/**/",
"prettier": "prettier --single-quote --trailing-comma all --write \"src/**/*.js\"",
"jest:coverage": "node --harmony_proxies node_modules/.bin/jest --coverage && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js",
"precommit": "yarn run lint"
},
"repository": {
"type": "git",
@@ -47,6 +50,7 @@
"eslint-plugin-prettier": "^2.1.1",
"eslint-plugin-react": "^6.9.0",
"flow-bin": "0.42.0",
"husky": "^0.14.3",
"jest": "^19.0.2",
"prettier": "^1.3.1",
"react": "16.0.0-alpha.6",
@@ -7,31 +7,31 @@ import reactConnectionStore from './reactConnectionStore';
type DefaultProps = {
timeout?: number,
pingServerUrl?: string
pingServerUrl?: string,
};
type Props = DefaultProps & {
children: (isConnected: boolean) => React$Element<any>
children: (isConnected: boolean) => React$Element<any>,
};
type State = {
isConnected: boolean
isConnected: boolean,
};
class ConnectivityRenderer extends Component<DefaultProps, Props, State> {
static propTypes = {
children: PropTypes.func.isRequired,
timeout: PropTypes.number,
pingServerUrl: PropTypes.string
pingServerUrl: PropTypes.string,
};
static defaultProps: DefaultProps = {
timeout: 3000,
pingServerUrl: 'https://google.com'
pingServerUrl: 'https://google.com',
};
state = {
isConnected: reactConnectionStore.getConnection()
isConnected: reactConnectionStore.getConnection(),
};
componentWillMount() {
@@ -52,7 +52,7 @@ class ConnectivityRenderer extends Component<DefaultProps, Props, State> {
if (Platform.OS === 'android') {
NetInfo.isConnected
.fetch()
.then(isConnected => this.checkInternet(isConnected));
.then((isConnected: boolean) => this.checkInternet(isConnected));
}
}
@@ -64,8 +64,8 @@ class ConnectivityRenderer extends Component<DefaultProps, Props, State> {
checkInternetAccess(
isConnected,
this.props.timeout,
this.props.pingServerUrl
).then(hasInternetAccess => {
this.props.pingServerUrl,
).then((hasInternetAccess: boolean) => {
this.handleConnectivityChange(hasInternetAccess);
});
};
@@ -74,7 +74,7 @@ class ConnectivityRenderer extends Component<DefaultProps, Props, State> {
reactConnectionStore.setConnection(isConnected);
if (isConnected !== this.state.isConnected) {
this.setState({
isConnected
isConnected,
});
}
};
Oops, something went wrong.

0 comments on commit 2a27c6c

Please sign in to comment.