diff --git a/extension/.babelrc b/extension/.babelrc
index 120f832f..6cc845b9 100644
--- a/extension/.babelrc
+++ b/extension/.babelrc
@@ -1,4 +1,4 @@
{
- "presets": [ "es2015", "stage-0", "react" ],
- "plugins": [ "add-module-exports", "transform-decorators-legacy" ]
+ "presets": ["es2015", "stage-0", "react"],
+ "plugins": ["add-module-exports", "transform-decorators-legacy"]
}
diff --git a/extension/.eslintrc b/extension/.eslintrc
index 6233bd94..7cbb31e0 100644
--- a/extension/.eslintrc
+++ b/extension/.eslintrc
@@ -15,18 +15,16 @@
"react/jsx-quotes": 0,
"block-scoped-var": 0,
"padded-blocks": 0,
- "quotes": [ 1, "single" ],
- "comma-style": [ 2, "last" ],
+ "quotes": [1, "single"],
+ "comma-style": [2, "last"],
"no-use-before-define": [0, "nofunc"],
"func-names": 0,
"prefer-const": 0,
"comma-dangle": 0,
"id-length": 0,
- "indent": [2, 2, {"SwitchCase": 1}],
+ "indent": [2, 2, { "SwitchCase": 1 }],
"new-cap": [2, { "capIsNewExceptions": ["Test"] }],
"default-case": 0
},
- "plugins": [
- "react"
- ]
-}
\ No newline at end of file
+ "plugins": ["react"]
+}
diff --git a/extension/.travis.yml b/extension/.travis.yml
index 2ea62360..d03640f9 100644
--- a/extension/.travis.yml
+++ b/extension/.travis.yml
@@ -2,7 +2,7 @@ sudo: required
dist: trusty
language: node_js
node_js:
- - "6"
+ - '6'
cache:
directories:
- $HOME/.yarn-cache
@@ -19,7 +19,7 @@ addons:
- g++-4.8
install:
- - "/sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_99.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :99 -ac -screen 0 1280x1024x16"
+ - '/sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_99.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :99 -ac -screen 0 1280x1024x16'
- npm install -g yarn
- yarn install
diff --git a/extension/CODE_OF_CONDUCT.md b/extension/CODE_OF_CONDUCT.md
index 81f485ba..c44e8369 100644
--- a/extension/CODE_OF_CONDUCT.md
+++ b/extension/CODE_OF_CONDUCT.md
@@ -14,22 +14,22 @@ appearance, race, religion, or sexual identity and orientation.
Examples of behavior that contributes to creating a positive environment
include:
-* Using welcoming and inclusive language
-* Being respectful of differing viewpoints and experiences
-* Gracefully accepting constructive criticism
-* Focusing on what is best for the community
-* Showing empathy towards other community members
+- Using welcoming and inclusive language
+- Being respectful of differing viewpoints and experiences
+- Gracefully accepting constructive criticism
+- Focusing on what is best for the community
+- Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
-* The use of sexualized language or imagery and unwelcome sexual attention or
- advances
-* Trolling, insulting/derogatory comments, and personal or political attacks
-* Public or private harassment
-* Publishing others' private information, such as a physical or electronic
- address, without explicit permission
-* Other conduct which could reasonably be considered inappropriate in a
- professional setting
+- The use of sexualized language or imagery and unwelcome sexual attention or
+ advances
+- Trolling, insulting/derogatory comments, and personal or political attacks
+- Public or private harassment
+- Publishing others' private information, such as a physical or electronic
+ address, without explicit permission
+- Other conduct which could reasonably be considered inappropriate in a
+ professional setting
## Our Responsibilities
diff --git a/extension/README.md b/extension/README.md
index 35145dbb..74167cce 100644
--- a/extension/README.md
+++ b/extension/README.md
@@ -2,7 +2,7 @@
[](https://gitter.im/zalmoxisus/redux-devtools-extension?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[](http://makeapullrequest.com)
-[](#backers)
+[](#backers)
[](#sponsors)

@@ -10,29 +10,35 @@
## Installation
### 1. For Chrome
- - from [Chrome Web Store](https://chrome.google.com/webstore/detail/redux-devtools/lmhkpmbekcpmknklioeibfkpmmfibljd);
- - or download `extension.zip` from [last releases](https://github.com/zalmoxisus/redux-devtools-extension/releases), unzip, open `chrome://extensions` url and turn on developer mode from top left and then click; on `Load Unpacked` and select the extracted folder for use
- - or build it with `npm i && npm run build:extension` and [load the extension's folder](https://developer.chrome.com/extensions/getstarted#unpacked) `./build/extension`;
- - or run it in dev mode with `npm i && npm start` and [load the extension's folder](https://developer.chrome.com/extensions/getstarted#unpacked) `./dev`.
+
+- from [Chrome Web Store](https://chrome.google.com/webstore/detail/redux-devtools/lmhkpmbekcpmknklioeibfkpmmfibljd);
+- or download `extension.zip` from [last releases](https://github.com/zalmoxisus/redux-devtools-extension/releases), unzip, open `chrome://extensions` url and turn on developer mode from top left and then click; on `Load Unpacked` and select the extracted folder for use
+- or build it with `npm i && npm run build:extension` and [load the extension's folder](https://developer.chrome.com/extensions/getstarted#unpacked) `./build/extension`;
+- or run it in dev mode with `npm i && npm start` and [load the extension's folder](https://developer.chrome.com/extensions/getstarted#unpacked) `./dev`.
### 2. For Firefox
- - from [Mozilla Add-ons](https://addons.mozilla.org/en-US/firefox/addon/reduxdevtools/);
- - or build it with `npm i && npm run build:firefox` and [load the extension's folder](https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Temporary_Installation_in_Firefox) `./build/firefox` (just select a file from inside the dir).
+
+- from [Mozilla Add-ons](https://addons.mozilla.org/en-US/firefox/addon/reduxdevtools/);
+- or build it with `npm i && npm run build:firefox` and [load the extension's folder](https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Temporary_Installation_in_Firefox) `./build/firefox` (just select a file from inside the dir).
### 3. For Electron
- - just specify `REDUX_DEVTOOLS` in [`electron-devtools-installer`](https://github.com/GPMDP/electron-devtools-installer).
+
+- just specify `REDUX_DEVTOOLS` in [`electron-devtools-installer`](https://github.com/GPMDP/electron-devtools-installer).
### 4. For other browsers and non-browser environment
- - use [`remote-redux-devtools`](https://github.com/zalmoxisus/remote-redux-devtools).
+
+- use [`remote-redux-devtools`](https://github.com/zalmoxisus/remote-redux-devtools).
## Usage
-> Note that starting from v2.7, `window.devToolsExtension` was renamed to `window.__REDUX_DEVTOOLS_EXTENSION__` / `window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__`.
+> Note that starting from v2.7, `window.devToolsExtension` was renamed to `window.__REDUX_DEVTOOLS_EXTENSION__` / `window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__`.
## 1. With Redux
+
### 1.1 Basic store
-
+
For a basic [Redux store](https://redux.js.org/api/createstore#createstorereducer-preloadedstate-enhancer) simply add:
+
```diff
const store = createStore(
reducer, /* preloadedState, */
@@ -43,16 +49,22 @@ For a basic [Redux store](https://redux.js.org/api/createstore#createstorereduce
Note that [`preloadedState`](https://redux.js.org/api/createstore#createstorereducer-preloadedstate-enhancer) argument is optional in Redux's [`createStore`](https://redux.js.org/api/createstore#createstorereducer-preloadedstate-enhancer).
> For universal ("isomorphic") apps, prefix it with `typeof window !== 'undefined' &&`.
+
```js
-const composeEnhancers = (typeof window !== 'undefined' && window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__) || compose;
+const composeEnhancers =
+ (typeof window !== 'undefined' &&
+ window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__) ||
+ compose;
```
> For TypeScript use [`redux-devtools-extension` npm package](#13-use-redux-devtools-extension-package-from-npm), which contains all the definitions, or just use `(window as any)` (see [Recipes](/docs/Recipes.md#using-in-a-typescript-project) for an example).
+
```js
const composeEnhancers = (window as any).__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
```
In case ESLint is configured to not allow using the underscore dangle, wrap it like so:
+
```diff
+ /* eslint-disable no-underscore-dangle */
const store = createStore(
@@ -67,7 +79,9 @@ In case ESLint is configured to not allow using the underscore dangle, wrap it l
> You don't need to npm install [`redux-devtools`](https://github.com/gaearon/redux-devtools) when using the extension (that's a different lib).
### 1.2 Advanced store setup
+
If you setup your store with [middleware and enhancers](http://redux.js.org/docs/api/applyMiddleware.html), change:
+
```diff
import { createStore, applyMiddleware, compose } from 'redux';
@@ -77,19 +91,21 @@ If you setup your store with [middleware and enhancers](http://redux.js.org/docs
applyMiddleware(...middleware)
));
```
+
> Note that when the extension is not installed, we’re using Redux compose here.
-
+
To specify [extension’s options](https://github.com/zalmoxisus/redux-devtools-extension/blob/master/docs/API/Arguments.md), use it like so:
+
```js
const composeEnhancers =
- typeof window === 'object' &&
- window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ ?
- window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({
- // Specify extension’s options like name, actionsBlacklist, actionsCreators, serialize...
- }) : compose;
+ typeof window === 'object' && window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__
+ ? window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({
+ // Specify extension’s options like name, actionsBlacklist, actionsCreators, serialize...
+ })
+ : compose;
const enhancer = composeEnhancers(
- applyMiddleware(...middleware),
+ applyMiddleware(...middleware)
// other store enhancers if any
);
const store = createStore(reducer, enhancer);
@@ -100,20 +116,28 @@ const store = createStore(reducer, enhancer);
### 1.3 Use `redux-devtools-extension` package from npm
To make things easier, there's an npm package to install:
+
```
npm install --save redux-devtools-extension
```
+
and to use like so:
+
```js
import { createStore, applyMiddleware } from 'redux';
import { composeWithDevTools } from 'redux-devtools-extension';
-const store = createStore(reducer, composeWithDevTools(
- applyMiddleware(...middleware),
- // other store enhancers if any
-));
+const store = createStore(
+ reducer,
+ composeWithDevTools(
+ applyMiddleware(...middleware)
+ // other store enhancers if any
+ )
+);
```
+
To specify [extension’s options](https://github.com/zalmoxisus/redux-devtools-extension/blob/master/docs/API/Arguments.md#windowdevtoolsextensionconfig):
+
```js
import { createStore, applyMiddleware } from 'redux';
import { composeWithDevTools } from 'redux-devtools-extension';
@@ -121,87 +145,109 @@ import { composeWithDevTools } from 'redux-devtools-extension';
const composeEnhancers = composeWithDevTools({
// Specify name here, actionsBlacklist, actionsCreators and other options if needed
});
-const store = createStore(reducer, /* preloadedState, */ composeEnhancers(
- applyMiddleware(...middleware),
- // other store enhancers if any
-));
-```
+const store = createStore(
+ reducer,
+ /* preloadedState, */ composeEnhancers(
+ applyMiddleware(...middleware)
+ // other store enhancers if any
+ )
+);
+```
+
> There’re just [few lines of code](https://github.com/zalmoxisus/redux-devtools-extension/blob/master/npm-package/index.js) added to your bundle.
In case you don't include other enhancers and middlewares, just use `devToolsEnhancer`:
+
```js
import { createStore } from 'redux';
import { devToolsEnhancer } from 'redux-devtools-extension';
-const store = createStore(reducer, /* preloadedState, */ devToolsEnhancer(
+const store = createStore(
+ reducer,
+ /* preloadedState, */ devToolsEnhancer()
// Specify name here, actionsBlacklist, actionsCreators and other options if needed
-));
-```
+);
+```
### 1.4 Using in production
-It's useful to include the extension in production as well. Usually you [can use it for development](https://medium.com/@zalmoxis/using-redux-devtools-in-production-4c5b56c5600f).
+
+It's useful to include the extension in production as well. Usually you [can use it for development](https://medium.com/@zalmoxis/using-redux-devtools-in-production-4c5b56c5600f).
If you want to restrict it there, use `redux-devtools-extension/logOnlyInProduction`:
+
```js
import { createStore } from 'redux';
import { devToolsEnhancer } from 'redux-devtools-extension/logOnlyInProduction';
-const store = createStore(reducer, /* preloadedState, */ devToolsEnhancer(
+const store = createStore(
+ reducer,
+ /* preloadedState, */ devToolsEnhancer()
// options like actionSanitizer, stateSanitizer
-));
+);
```
+
or with middlewares and enhancers:
- ```js
- import { createStore, applyMiddleware } from 'redux';
- import { composeWithDevTools } from 'redux-devtools-extension/logOnlyInProduction';
- const composeEnhancers = composeWithDevTools({
- // options like actionSanitizer, stateSanitizer
- });
- const store = createStore(reducer, /* preloadedState, */ composeEnhancers(
- applyMiddleware(...middleware),
- // other store enhancers if any
- ));
- ```
-> You'll have to add `'process.env.NODE_ENV': JSON.stringify('production')` in your Webpack config for the production bundle ([to envify](https://github.com/gaearon/redux-devtools/blob/master/docs/Walkthrough.md#exclude-devtools-from-production-builds)). If you use `create-react-app`, [it already does it for you.](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/config/webpack.config.prod.js#L253-L257)
+```js
+import { createStore, applyMiddleware } from 'redux';
+import { composeWithDevTools } from 'redux-devtools-extension/logOnlyInProduction';
- If you're already checking `process.env.NODE_ENV` when creating the store, include `redux-devtools-extension/logOnly` for production environment.
+const composeEnhancers = composeWithDevTools({
+ // options like actionSanitizer, stateSanitizer
+});
+const store = createStore(
+ reducer,
+ /* preloadedState, */ composeEnhancers(
+ applyMiddleware(...middleware)
+ // other store enhancers if any
+ )
+);
+```
- If you don’t want to allow the extension in production, just use `redux-devtools-extension/developmentOnly`.
+> You'll have to add `'process.env.NODE_ENV': JSON.stringify('production')` in your Webpack config for the production bundle ([to envify](https://github.com/gaearon/redux-devtools/blob/master/docs/Walkthrough.md#exclude-devtools-from-production-builds)). If you use `create-react-app`, [it already does it for you.](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/config/webpack.config.prod.js#L253-L257)
-> See [the article](https://medium.com/@zalmoxis/using-redux-devtools-in-production-4c5b56c5600f) for more details.
+If you're already checking `process.env.NODE_ENV` when creating the store, include `redux-devtools-extension/logOnly` for production environment.
+
+If you don’t want to allow the extension in production, just use `redux-devtools-extension/developmentOnly`.
+
+> See [the article](https://medium.com/@zalmoxis/using-redux-devtools-in-production-4c5b56c5600f) for more details.
### 1.5 For React Native, hybrid, desktop and server side Redux apps
+
For React Native we can use [`react-native-debugger`](https://github.com/jhen0409/react-native-debugger), which already included [the same API](https://github.com/jhen0409/react-native-debugger/blob/master/docs/redux-devtools-integration.md) with Redux DevTools Extension.
For most platforms, include [`Remote Redux DevTools`](https://github.com/zalmoxisus/remote-redux-devtools)'s store enhancer, and from the extension's context menu choose 'Open Remote DevTools' for remote monitoring.
## 2. Without Redux
+
See [integrations](docs/Integrations.md) and [the blog post](https://medium.com/@zalmoxis/redux-devtools-without-redux-or-how-to-have-a-predictable-state-with-any-architecture-61c5f5a7716f) for more details on how to use the extension with any architecture.
-
+
## Docs
- - [Options (arguments)](docs/API/Arguments.md)
- - [Methods (advanced API)](docs/API/Methods.md)
- - [FAQ](docs/FAQ.md)
- - Features
- - [Trace actions calls](/docs/Features/Trace.md)
- - [Troubleshooting](docs/Troubleshooting.md)
- - [Articles](docs/Articles.md)
- - [Videos](docs/Videos.md)
- - [Feedback](docs/Feedback.md)
+
+- [Options (arguments)](docs/API/Arguments.md)
+- [Methods (advanced API)](docs/API/Methods.md)
+- [FAQ](docs/FAQ.md)
+- Features
+ - [Trace actions calls](/docs/Features/Trace.md)
+- [Troubleshooting](docs/Troubleshooting.md)
+- [Articles](docs/Articles.md)
+- [Videos](docs/Videos.md)
+- [Feedback](docs/Feedback.md)
## Demo
+
Live demos to use the extension with:
- - [Counter](http://zalmoxisus.github.io/examples/counter/)
- - [TodoMVC](http://zalmoxisus.github.io/examples/todomvc/)
- - [Redux Form](http://redux-form.com/6.5.0/examples/simple/)
- - [React Tetris](https://chvin.github.io/react-tetris/?lan=en)
- - [Book Collection (Angular ngrx store)](https://ngrx.github.io/platform/example-app/)
+- [Counter](http://zalmoxisus.github.io/examples/counter/)
+- [TodoMVC](http://zalmoxisus.github.io/examples/todomvc/)
+- [Redux Form](http://redux-form.com/6.5.0/examples/simple/)
+- [React Tetris](https://chvin.github.io/react-tetris/?lan=en)
+- [Book Collection (Angular ngrx store)](https://ngrx.github.io/platform/example-app/)
Also see [`./examples` folder](https://github.com/zalmoxisus/redux-devtools-extension/tree/master/examples).
## Backers
+
Support us with a monthly donation and help us continue our activities. [[Become a backer](https://opencollective.com/redux-devtools-extension#backer)]
@@ -235,8 +281,8 @@ Support us with a monthly donation and help us continue our activities. [[Become
-
## Sponsors
+
Become a sponsor and get your logo on our README on Github with a link to your site. [[Become a sponsor](https://opencollective.com/redux-devtools-extension#sponsor)]
diff --git a/extension/SUMMARY.md b/extension/SUMMARY.md
index 0b731dfc..542612fd 100644
--- a/extension/SUMMARY.md
+++ b/extension/SUMMARY.md
@@ -1 +1 @@
-./docs/README.md
\ No newline at end of file
+./docs/README.md
diff --git a/extension/appveyor.yml b/extension/appveyor.yml
index 83262e78..884e5b13 100644
--- a/extension/appveyor.yml
+++ b/extension/appveyor.yml
@@ -3,7 +3,7 @@ environment:
- nodejs_version: '6'
cache:
- - "%LOCALAPPDATA%/Yarn"
+ - '%LOCALAPPDATA%/Yarn'
- node_modules
install:
diff --git a/extension/book.json b/extension/book.json
index 36d8eb57..d7f27743 100644
--- a/extension/book.json
+++ b/extension/book.json
@@ -15,4 +15,4 @@
"twitter": true
}
}
-}
\ No newline at end of file
+}
diff --git a/extension/docs/API/Arguments.md b/extension/docs/API/Arguments.md
index b92737a3..fe632424 100644
--- a/extension/docs/API/Arguments.md
+++ b/extension/docs/API/Arguments.md
@@ -1,98 +1,141 @@
# Options
Use with
- - `window.__REDUX_DEVTOOLS_EXTENSION__([options])`
- - `window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__([options])()`
- - `window.__REDUX_DEVTOOLS_EXTENSION__.connect([options])`
- - `redux-devtools-extension` npm package:
- ```js
- import { composeWithDevTools } from 'redux-devtools-extension';
- const composeEnhancers = composeWithDevTools(options);
- const store = createStore(reducer, /* preloadedState, */ composeEnhancers(
- applyMiddleware(...middleware),
+- `window.__REDUX_DEVTOOLS_EXTENSION__([options])`
+- `window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__([options])()`
+- `window.__REDUX_DEVTOOLS_EXTENSION__.connect([options])`
+- `redux-devtools-extension` npm package:
+
+```js
+import { composeWithDevTools } from 'redux-devtools-extension';
+
+const composeEnhancers = composeWithDevTools(options);
+const store = createStore(
+ reducer,
+ /* preloadedState, */ composeEnhancers(
+ applyMiddleware(...middleware)
// other store enhancers if any
- ));
- ```
+ )
+);
+```
The `options` object is optional, and can include any of the following.
### `name`
-*string* - the instance name to be shown on the monitor page. Default value is `document.title`. If not specified and there's no document title, it will consist of `tabId` and `instanceId`.
-
+
+_string_ - the instance name to be shown on the monitor page. Default value is `document.title`. If not specified and there's no document title, it will consist of `tabId` and `instanceId`.
+
### `actionCreators`
-*array* or *object* - action creators functions to be available in the Dispatcher. See [the example](https://github.com/zalmoxisus/redux-devtools-extension/commit/477e69d8649dfcdc9bf84dd45605dab7d9775c03).
+
+_array_ or _object_ - action creators functions to be available in the Dispatcher. See [the example](https://github.com/zalmoxisus/redux-devtools-extension/commit/477e69d8649dfcdc9bf84dd45605dab7d9775c03).
### `latency`
-*number (in ms)* - if more than one action is dispatched in the indicated interval, all new actions will be collected and sent at once. It is the joint between performance and speed. When set to `0`, all actions will be sent instantly. Set it to a higher value when experiencing perf issues (also `maxAge` to a lower value). Default is `500 ms`.
-
+
+_number (in ms)_ - if more than one action is dispatched in the indicated interval, all new actions will be collected and sent at once. It is the joint between performance and speed. When set to `0`, all actions will be sent instantly. Set it to a higher value when experiencing perf issues (also `maxAge` to a lower value). Default is `500 ms`.
+
### `maxAge`
-*number* (>1) - maximum allowed actions to be stored in the history tree. The oldest actions are removed once maxAge is reached. It's critical for performance. Default is `50`.
+
+_number_ (>1) - maximum allowed actions to be stored in the history tree. The oldest actions are removed once maxAge is reached. It's critical for performance. Default is `50`.
### `trace`
-*boolean* or *function* - if set to `true`, will include stack trace for every dispatched action, so you can see it in trace tab jumping directly to that part of code ([more details](../Features/Trace.md)). You can use a function (with action object as argument) which should return `new Error().stack` string, getting the stack outside of reducers. Default to `false`.
+
+_boolean_ or _function_ - if set to `true`, will include stack trace for every dispatched action, so you can see it in trace tab jumping directly to that part of code ([more details](../Features/Trace.md)). You can use a function (with action object as argument) which should return `new Error().stack` string, getting the stack outside of reducers. Default to `false`.
### `traceLimit`
-*number* - maximum stack trace frames to be stored (in case `trace` option was provided as `true`). By default it's `10`. Note that, because extension's calls are excluded, the resulted frames could be 1 less. If `trace` option is a function, `traceLimit` will have no effect, as it's supposed to be handled there.
+
+_number_ - maximum stack trace frames to be stored (in case `trace` option was provided as `true`). By default it's `10`. Note that, because extension's calls are excluded, the resulted frames could be 1 less. If `trace` option is a function, `traceLimit` will have no effect, as it's supposed to be handled there.
### `serialize`
-*boolean* or *object* which contains:
+
+_boolean_ or _object_ which contains:
- **options** `object or boolean`:
- - `undefined` - will use regular `JSON.stringify` to send data (it's the fast mode).
- - `false` - will handle also circular references.
- - `true` - will handle also date, regex, undefined, primitives, error objects, symbols, maps, sets and functions.
- - object, which contains `date`, `regex`, `undefined`, `nan`, `infinity`, `error`, `symbol`, `map`, `set` and `function` keys. For each of them you can indicate if to include (by setting as `true`). For `function` key you can also specify a custom function which handles serialization. See [`jsan`](https://github.com/kolodny/jsan) for more details. Example:
- ```js
- const store = Redux.createStore(reducer, window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__({
- serialize: {
- options: {
- undefined: true,
- function: function(fn) { return fn.toString() }
- }
- }
- }));
- ```
+ - `undefined` - will use regular `JSON.stringify` to send data (it's the fast mode).
+ - `false` - will handle also circular references.
+ - `true` - will handle also date, regex, undefined, primitives, error objects, symbols, maps, sets and functions.
+ - object, which contains `date`, `regex`, `undefined`, `nan`, `infinity`, `error`, `symbol`, `map`, `set` and `function` keys. For each of them you can indicate if to include (by setting as `true`). For `function` key you can also specify a custom function which handles serialization. See [`jsan`](https://github.com/kolodny/jsan) for more details. Example:
+
+ ```js
+ const store = Redux.createStore(
+ reducer,
+ window.__REDUX_DEVTOOLS_EXTENSION__ &&
+ window.__REDUX_DEVTOOLS_EXTENSION__({
+ serialize: {
+ options: {
+ undefined: true,
+ function: function (fn) {
+ return fn.toString();
+ },
+ },
+ },
+ })
+ );
+ ```
- **replacer** `function(key, value)` - [JSON `replacer` function](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify#The_replacer_parameter) used for both actions and states stringify.
Example of usage with [mori data structures](https://github.com/swannodette/mori):
+
```js
- const store = Redux.createStore(reducer, window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__({
- serialize: {
- replacer: (key, value) => value && mori.isMap(value) ? mori.toJs(value) : value
- }
- }));
+ const store = Redux.createStore(
+ reducer,
+ window.__REDUX_DEVTOOLS_EXTENSION__ &&
+ window.__REDUX_DEVTOOLS_EXTENSION__({
+ serialize: {
+ replacer: (key, value) =>
+ value && mori.isMap(value) ? mori.toJs(value) : value,
+ },
+ })
+ );
```
+
In addition, you can specify a data type by adding a [`__serializedType__`](https://github.com/zalmoxisus/remotedev-serialize/blob/master/helpers/index.js#L4) key. So you can deserialize it back while importing or persisting data. Moreover, it will also [show a nice preview showing the provided custom type](https://cloud.githubusercontent.com/assets/7957859/21814330/a17d556a-d761-11e6-85ef-159dd12f36c5.png):
+
```js
- const store = Redux.createStore(reducer, window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__({
- serialize: {
- replacer: (key, value) => {
- if (Immutable.List.isList(value)) { // use your custom data type checker
- return {
- data: value.toArray(), // ImmutableJS custom method to get JS data as array
- __serializedType__: 'ImmutableList' // mark you custom data type to show and retrieve back
- }
- }
- }
- }
- }));
+ const store = Redux.createStore(
+ reducer,
+ window.__REDUX_DEVTOOLS_EXTENSION__ &&
+ window.__REDUX_DEVTOOLS_EXTENSION__({
+ serialize: {
+ replacer: (key, value) => {
+ if (Immutable.List.isList(value)) {
+ // use your custom data type checker
+ return {
+ data: value.toArray(), // ImmutableJS custom method to get JS data as array
+ __serializedType__: 'ImmutableList', // mark you custom data type to show and retrieve back
+ };
+ }
+ },
+ },
+ })
+ );
```
+
- **reviver** `function(key, value)` - [JSON `reviver` function](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse#Using_the_reviver_parameter) used for parsing the imported actions and states. See [`remotedev-serialize`](https://github.com/zalmoxisus/remotedev-serialize/blob/master/immutable/serialize.js#L8-L41) as an example on how to serialize special data types and get them back:
+
```js
- const store = Redux.createStore(reducer, window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__({
- serialize: {
- reviver: (key, value) => {
- if (typeof value === 'object' && value !== null && '__serializedType__' in value) {
- switch (value.__serializedType__) {
- case 'ImmutableList': return Immutable.List(value.data);
- }
- }
- }
- }
- }));
+ const store = Redux.createStore(
+ reducer,
+ window.__REDUX_DEVTOOLS_EXTENSION__ &&
+ window.__REDUX_DEVTOOLS_EXTENSION__({
+ serialize: {
+ reviver: (key, value) => {
+ if (
+ typeof value === 'object' &&
+ value !== null &&
+ '__serializedType__' in value
+ ) {
+ switch (value.__serializedType__) {
+ case 'ImmutableList':
+ return Immutable.List(value.data);
+ }
+ }
+ },
+ },
+ })
+ );
```
- **immutable** `object` - automatically serialize/deserialize immutablejs via [remotedev-serialize](https://github.com/zalmoxisus/remotedev-serialize). Just pass the Immutable library like so:
@@ -101,134 +144,181 @@ The `options` object is optional, and can include any of the following.
import Immutable from 'immutable'; // https://facebook.github.io/immutable-js/
// ...
// Like above, only showing off compose this time. Reminder you might not want this in prod.
- const composeEnhancers = typeof window === 'object' && typeof window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ !== 'undefined' ?
- window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({
- serialize: {
- immutable: Immutable
- }
- }) : compose;
+ const composeEnhancers =
+ typeof window === 'object' &&
+ typeof window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ !== 'undefined'
+ ? window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({
+ serialize: {
+ immutable: Immutable,
+ },
+ })
+ : compose;
```
+
It will support all ImmutableJS structures. You can even export them into a file and get them back. The only exception is `Record` class, for which you should pass in addition the references to your classes in `refs`.
+
- **refs** `array` - ImmutableJS `Record` classes used to make possible restore its instances back when importing, persisting... Example of usage:
- ``` js
+
+ ```js
import Immutable from 'immutable';
// ...
-
- const ABRecord = Immutable.Record({ a:1, b:2 });
- const myRecord = new ABRecord({ b:3 }); // used in the reducers
-
- const store = createStore(rootReducer, window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__({
- serialize: {
- immutable: Immutable,
- refs: [ABRecord]
- }
- }));
+
+ const ABRecord = Immutable.Record({ a: 1, b: 2 });
+ const myRecord = new ABRecord({ b: 3 }); // used in the reducers
+
+ const store = createStore(
+ rootReducer,
+ window.__REDUX_DEVTOOLS_EXTENSION__ &&
+ window.__REDUX_DEVTOOLS_EXTENSION__({
+ serialize: {
+ immutable: Immutable,
+ refs: [ABRecord],
+ },
+ })
+ );
```
-
+
Also you can specify alternative values right in the state object (in the initial state of the reducer) by adding `toJSON` function:
In the example bellow it will always send `{ component: '[React]' }`, regardless of the state's `component` value (useful when you don't want to send lots of unnecessary data):
+
```js
function component(
- state = { component: null, toJSON: () => ({ component: '[React]' }) },
+ state = { component: null, toJSON: () => ({ component: '[React]' }) },
action
) {
switch (action.type) {
- case 'ADD_COMPONENT': return { component: action.component };
- default: return state;
+ case 'ADD_COMPONENT':
+ return { component: action.component };
+ default:
+ return state;
}
}
```
-You could also alter the value. For example when state is `{ count: 1 }`, we'll send `{ counter: 10 }` (notice we don't have an arrow function this time to use the object's `this`):
+You could also alter the value. For example when state is `{ count: 1 }`, we'll send `{ counter: 10 }` (notice we don't have an arrow function this time to use the object's `this`):
+
```js
function counter(
- state = { count: 0, toJSON: function (){ return { conter: this.count * 10 }; } },
+ state = {
+ count: 0,
+ toJSON: function () {
+ return { conter: this.count * 10 };
+ },
+ },
action
) {
switch (action.type) {
- case 'INCREMENT': return { count: state.count + 1 };
- default: return state;
+ case 'INCREMENT':
+ return { count: state.count + 1 };
+ default:
+ return state;
}
}
```
### `actionSanitizer` / `stateSanitizer`
-- **actionSanitizer** (*function*) - function which takes `action` object and id number as arguments, and should return `action` object back. See the example bellow.
-- **stateSanitizer** (*function*) - function which takes `state` object and index as arguments, and should return `state` object back.
+
+- **actionSanitizer** (_function_) - function which takes `action` object and id number as arguments, and should return `action` object back. See the example bellow.
+- **stateSanitizer** (_function_) - function which takes `state` object and index as arguments, and should return `state` object back.
Example of usage:
```js
-const actionSanitizer = (action) => (
- action.type === 'FILE_DOWNLOAD_SUCCESS' && action.data ?
- { ...action, data: '<>' } : action
+const actionSanitizer = (action) =>
+ action.type === 'FILE_DOWNLOAD_SUCCESS' && action.data
+ ? { ...action, data: '<>' }
+ : action;
+const store = createStore(
+ rootReducer,
+ window.__REDUX_DEVTOOLS_EXTENSION__ &&
+ window.__REDUX_DEVTOOLS_EXTENSION__({
+ actionSanitizer,
+ stateSanitizer: (state) =>
+ state.data ? { ...state, data: '<>' } : state,
+ })
);
-const store = createStore(rootReducer, window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__({
- actionSanitizer,
- stateSanitizer: (state) => state.data ? { ...state, data: '<>' } : state
-}));
```
### `actionsBlacklist` / `actionsWhitelist`
-*string or array of strings as regex* - actions types to be hidden / shown in the monitors (while passed to the reducers). If `actionsWhitelist` specified, `actionsBlacklist` is ignored.
+
+_string or array of strings as regex_ - actions types to be hidden / shown in the monitors (while passed to the reducers). If `actionsWhitelist` specified, `actionsBlacklist` is ignored.
Example:
+
```js
-createStore(reducer, remotedev({
- sendTo: 'http://localhost:8000',
- actionsBlacklist: 'SOME_ACTION'
- // or actionsBlacklist: ['SOME_ACTION', 'SOME_OTHER_ACTION']
- // or just actionsBlacklist: 'SOME_' to omit both
-}))
+createStore(
+ reducer,
+ remotedev({
+ sendTo: 'http://localhost:8000',
+ actionsBlacklist: 'SOME_ACTION',
+ // or actionsBlacklist: ['SOME_ACTION', 'SOME_OTHER_ACTION']
+ // or just actionsBlacklist: 'SOME_' to omit both
+ })
+);
```
### `predicate`
-*function* - called for every action before sending, takes `state` and `action` object, and returns `true` in case it allows sending the current data to the monitor. Use it as a more advanced version of `actionsBlacklist`/`actionsWhitelist` parameters.
+
+_function_ - called for every action before sending, takes `state` and `action` object, and returns `true` in case it allows sending the current data to the monitor. Use it as a more advanced version of `actionsBlacklist`/`actionsWhitelist` parameters.
Example of usage:
```js
-const store = createStore(rootReducer, window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__({
- predicate: (state, action) => state.dev.logLevel === VERBOSE && !action.forwarded
-}));
+const store = createStore(
+ rootReducer,
+ window.__REDUX_DEVTOOLS_EXTENSION__ &&
+ window.__REDUX_DEVTOOLS_EXTENSION__({
+ predicate: (state, action) =>
+ state.dev.logLevel === VERBOSE && !action.forwarded,
+ })
+);
```
### `shouldRecordChanges`
-*boolean* - if specified as `false`, it will not record the changes till clicking on `Start recording` button. Default is `true`. Available only for Redux enhancer, for others use `autoPause`.
+
+_boolean_ - if specified as `false`, it will not record the changes till clicking on `Start recording` button. Default is `true`. Available only for Redux enhancer, for others use `autoPause`.
### `pauseActionType`
-*string* - if specified, whenever clicking on `Pause recording` button and there are actions in the history log, will add this action type. If not specified, will commit when paused. Available only for Redux enhancer. Default is `@@PAUSED`.
+
+_string_ - if specified, whenever clicking on `Pause recording` button and there are actions in the history log, will add this action type. If not specified, will commit when paused. Available only for Redux enhancer. Default is `@@PAUSED`.
### `autoPause`
-*boolean* - auto pauses when the extension’s window is not opened, and so has zero impact on your app when not in use. Not available for Redux enhancer (as it already does it but storing the data to be sent). Default is `false`.
+
+_boolean_ - auto pauses when the extension’s window is not opened, and so has zero impact on your app when not in use. Not available for Redux enhancer (as it already does it but storing the data to be sent). Default is `false`.
### `shouldStartLocked`
-*boolean* - if specified as `true`, it will not allow any non-monitor actions to be dispatched till clicking on `Unlock changes` button. Available only for Redux enhancer. Default is `false`.
+
+_boolean_ - if specified as `true`, it will not allow any non-monitor actions to be dispatched till clicking on `Unlock changes` button. Available only for Redux enhancer. Default is `false`.
### `shouldHotReload`
-*boolean* - if set to `false`, will not recompute the states on hot reloading (or on replacing the reducers). Available only for Redux enhancer. Default to `true`.
+
+_boolean_ - if set to `false`, will not recompute the states on hot reloading (or on replacing the reducers). Available only for Redux enhancer. Default to `true`.
### `shouldCatchErrors`
-*boolean* - if specified as `true`, whenever there's an exception in reducers, the monitors will show the error message, and next actions will not be dispatched.
+
+_boolean_ - if specified as `true`, whenever there's an exception in reducers, the monitors will show the error message, and next actions will not be dispatched.
### `features`
+
If you want to restrict the extension, just specify the features you allow:
+
```js
const composeEnhancers = composeWithDevTools({
features: {
pause: true, // start/pause recording of dispatched actions
- lock: true, // lock/unlock dispatching actions and side effects
+ lock: true, // lock/unlock dispatching actions and side effects
persist: true, // persist states on page reloading
export: true, // export history of actions in a file
import: 'custom', // import history of actions from a file
jump: true, // jump back and forth (time travelling)
skip: true, // skip (cancel) actions
- reorder: true, // drag and drop actions in the history list
+ reorder: true, // drag and drop actions in the history list
dispatch: true, // dispatch custom actions or action creators
- test: true // generate tests for the selected actions
+ test: true, // generate tests for the selected actions
},
// other options like actionSanitizer, stateSanitizer
});
```
+
If not specified, all of the features are enabled. When set as an object, only those included as `true` will be allowed.
Note that except `true`/`false`, `import` and `export` can be set as `custom` (which is by default for Redux enhancer), meaning that the importing/exporting occurs on the client side. Otherwise, you'll get/set the data right from the monitor part.
diff --git a/extension/docs/API/Methods.md b/extension/docs/API/Methods.md
index a2205d7a..3d637601 100644
--- a/extension/docs/API/Methods.md
+++ b/extension/docs/API/Methods.md
@@ -1,6 +1,6 @@
## Communicate with the extension directly
-> Note this is advanced API, which you usually don't need to use with Redux enhancer.
+> Note this is advanced API, which you usually don't need to use with Redux enhancer.
Use the following methods of `window.__REDUX_DEVTOOLS_EXTENSION__`:
@@ -12,18 +12,20 @@ Use the following methods of `window.__REDUX_DEVTOOLS_EXTENSION__`:
- [notifyErrors](#notifyerrors)
+
### connect([options])
##### Arguments
-- [`options`] *Object* - [see the available options](Arguments.md).
+- [`options`] _Object_ - [see the available options](Arguments.md).
##### Returns
-*Object* containing the following methods:
-- `subscribe(listener)` - adds a change listener. It will be called any time an action is dispatched from the monitor. Returns a function to unsubscribe the current listener.
+_Object_ containing the following methods:
+
+- `subscribe(listener)` - adds a change listener. It will be called any time an action is dispatched from the monitor. Returns a function to unsubscribe the current listener.
- `unsubscribe()` - unsubscribes all listeners.
-- `send(action, state)` - sends a new action and state manually to be shown on the monitor. If action is `null` then we suppose we send `liftedState`.
+- `send(action, state)` - sends a new action and state manually to be shown on the monitor. If action is `null` then we suppose we send `liftedState`.
- `init(state)` - sends the initial state to the monitor.
- `error(message)` - sends the error message to be shown in the extension's monitor.
@@ -37,51 +39,55 @@ devTools.subscribe((message) => {
}
});
devTools.init({ value: 'initial state' });
-devTools.send('change state', { value: 'state changed' })
+devTools.send('change state', { value: 'state changed' });
```
See [redux enhancer's example](https://github.com/zalmoxisus/redux-devtools-extension/blob/master/npm-package/logOnly.js), [react example](https://github.com/zalmoxisus/redux-devtools-extension/blob/master/examples/react-counter-messaging/components/Counter.js) and [blog post](https://medium.com/@zalmoxis/redux-devtools-without-redux-or-how-to-have-a-predictable-state-with-any-architecture-61c5f5a7716f) for more details.
### disconnect()
-Remove extensions listener and disconnect extensions background script connection. Usually just unsubscribing the listener inside the `connect` is enough.
+Remove extensions listener and disconnect extensions background script connection. Usually just unsubscribing the listener inside the `connect` is enough.
+
### send(action, state, [options, instanceId])
Send a new action and state manually to be shown on the monitor. It's recommended to use [`connect`](connect), unless you want to hook into an already created instance.
##### Arguments
-- `action` *String* (action type) or *Object* with required `type` key.
-- `state` *any* - usually object to expand.
-- [`options`] *Object* - [see the available options](Arguments.md).
-- [`instanceId`] *String* - instance id for which to include the log. If not specified and not present in the `options` object, will be the first available instance.
+- `action` _String_ (action type) or _Object_ with required `type` key.
+- `state` _any_ - usually object to expand.
+- [`options`] _Object_ - [see the available options](Arguments.md).
+- [`instanceId`] _String_ - instance id for which to include the log. If not specified and not present in the `options` object, will be the first available instance.
+
### listen(onMessage, instanceId)
Listen for messages dispatched for specific `instanceId`. For most cases it's better to use `subcribe` inside the [`connect`](connect).
##### Arguments
-- `onMessage` *Function* to call when there's an action from the monitor.
-- `instanceId` *String* - instance id for which to handle actions.
+- `onMessage` _Function_ to call when there's an action from the monitor.
+- `instanceId` _String_ - instance id for which to handle actions.
+
### open([position])
Open the extension's window. This should be conditional (usually you don't need to open extension's window automatically).
##### Arguments
-- [`position`] *String* - window position: `left`, `right`, `bottom`. Also can be `panel` to [open it in a Chrome panel](../FAQ.md#how-to-keep-devtools-window-focused-all-the-time-in-a-chrome-panel). Or `remote` to [open remote monitor](../FAQ.md#how-to-get-it-work-with-webworkers-react-native-hybrid-desktop-and-server-side-apps). By default is `left`.
+- [`position`] _String_ - window position: `left`, `right`, `bottom`. Also can be `panel` to [open it in a Chrome panel](../FAQ.md#how-to-keep-devtools-window-focused-all-the-time-in-a-chrome-panel). Or `remote` to [open remote monitor](../FAQ.md#how-to-get-it-work-with-webworkers-react-native-hybrid-desktop-and-server-side-apps). By default is `left`.
+
### notifyErrors([onError])
When called, the extension will listen for uncaught exceptions on the page, and, if any, will show native notifications. Optionally, you can provide a function to be called when an exception occurs.
##### Arguments
-- [`onError`] *Function* to call when there's an exceptions.
+- [`onError`] _Function_ to call when there's an exceptions.
diff --git a/extension/docs/Credits.md b/extension/docs/Credits.md
index 3c529914..f7ec16de 100644
--- a/extension/docs/Credits.md
+++ b/extension/docs/Credits.md
@@ -1,11 +1,11 @@
# Credits
- - Built using [Crossbuilder](https://github.com/zalmoxisus/crossbuilder) boilerplate.
- - Includes [Dan Abramov](https://github.com/gaearon)'s [redux-devtools](https://github.com/gaearon/redux-devtools) and the following monitors:
- - [Log Monitor](https://github.com/gaearon/redux-devtools-log-monitor)
- - [Inspector](https://github.com/alexkuz/redux-devtools-inspector)
- - [Dispatch](https://github.com/YoruNoHikage/redux-devtools-dispatch)
- - [Slider](https://github.com/calesce/redux-slider-monitor)
- - [Chart](https://github.com/romseguy/redux-devtools-chart-monitor)
- - [The logo icon](https://github.com/reactjs/redux/issues/151) made by [Keith Yong](https://github.com/keithyong) .
- - Examples from [Redux](https://github.com/rackt/redux/tree/master/examples).
+- Built using [Crossbuilder](https://github.com/zalmoxisus/crossbuilder) boilerplate.
+- Includes [Dan Abramov](https://github.com/gaearon)'s [redux-devtools](https://github.com/gaearon/redux-devtools) and the following monitors:
+ - [Log Monitor](https://github.com/gaearon/redux-devtools-log-monitor)
+ - [Inspector](https://github.com/alexkuz/redux-devtools-inspector)
+ - [Dispatch](https://github.com/YoruNoHikage/redux-devtools-dispatch)
+ - [Slider](https://github.com/calesce/redux-slider-monitor)
+ - [Chart](https://github.com/romseguy/redux-devtools-chart-monitor)
+- [The logo icon](https://github.com/reactjs/redux/issues/151) made by [Keith Yong](https://github.com/keithyong) .
+- Examples from [Redux](https://github.com/rackt/redux/tree/master/examples).
diff --git a/extension/docs/FAQ.md b/extension/docs/FAQ.md
index ee54ac9e..d46253b5 100644
--- a/extension/docs/FAQ.md
+++ b/extension/docs/FAQ.md
@@ -1,6 +1,7 @@
# Redux DevTools Extension FAQ
## Table of Contents
+
- [How to get it work](#how-to-get-it-work)
- [How to disable/enable it in production](#how-to-disable-it-in-production)
- [How to persist debug sessions across page reloads](#how-to-persist-debug-sessions-across-page-reloads)
@@ -10,22 +11,35 @@
- [Keyboard shortcuts](#keyboard-shortcuts)
#### How to get it work
+
- Check the extension with [Counter](http://zalmoxisus.github.io/examples/counter/) or [TodoMVC](http://zalmoxisus.github.io/examples/todomvc/) demo.
- Reload the extension on the extensions page (`chrome://extensions/`).
- If something goes wrong, [open an issue](https://github.com/zalmoxisus/redux-devtools-extension/issues) or tweet me: [@mdiordiev](https://twitter.com/mdiordiev).
#### How to disable it in production
-Usually you don't have to. See [the article for details on how to include it in production](https://medium.com/@zalmoxis/using-redux-devtools-in-production-4c5b56c5600f).
+
+Usually you don't have to. See [the article for details on how to include it in production](https://medium.com/@zalmoxis/using-redux-devtools-in-production-4c5b56c5600f).
+
#### How to persist debug sessions across page reloads
+
Just click the `Persist` button or add `?debug_session=` to the url.
+
#### How to open DevTools programmatically
+
```js
window.__REDUX_DEVTOOLS_EXTENSION__.open();
```
+
Make sure to have it conditionally. Auto opening windows is a bad DX. See the [API](https://github.com/zalmoxisus/redux-devtools-extension/blob/master/docs/API/Methods.md#open) for details.
+
#### How to enable/disable errors notifying
+
Just find `Redux DevTools` on the extensions page (`chrome://extensions/`) and click the `Options` link to customize everything. The errors notifying is disabled by default. If enabled, it works only when the store enhancer is called (in order not to show notifications for any sites you visit). In case you want notifications for a non-redux app, init it explicitly by calling `window.__REDUX_DEVTOOLS_EXTENSION__.notifyErrors()` (probably you'll check if `window.__REDUX_DEVTOOLS_EXTENSION__` exists before calling it).
+
#### How to get it work with WebWorkers, React Native, hybrid, desktop and server side apps
-It is not possible to inject extension's script there and to communicate directly. To solve this, use [Remote Redux DevTools](https://github.com/zalmoxisus/remote-redux-devtools). After including it inside the app, click `Remote` button for remote monitoring.
+
+It is not possible to inject extension's script there and to communicate directly. To solve this, use [Remote Redux DevTools](https://github.com/zalmoxisus/remote-redux-devtools). After including it inside the app, click `Remote` button for remote monitoring.
+
#### Keyboard shortcuts
+
To set/change the keyboard shortcuts, click "Keyboard shortcuts" button on the bottom of the extensions page (`chrome://extensions/`). By default only `Cmd` (`Ctrl`) + `Shift` + `E` is available, which will open the extension popup (only when the Redux store is available in the current page).
diff --git a/extension/docs/Integrations.md b/extension/docs/Integrations.md
index cb51130e..ae27c64f 100644
--- a/extension/docs/Integrations.md
+++ b/extension/docs/Integrations.md
@@ -1,6 +1,7 @@
# Integrations for js and non-js frameworks
Mostly functional:
+
- [React](#react)
- [Angular](#angular)
- [Cycle](#cycle)
@@ -13,26 +14,32 @@ Mostly functional:
- [Aurelia](#aurelia)
In progress:
+
- [ClojureScript](#clojurescript)
- [Horizon](#horizon)
- [Python](#python)
- [Swift](#swift)
### [React](https://github.com/facebook/react)
+
#### Inspect React props
+
##### [`react-inspect-props`](https://github.com/lucasconstantino/react-inspect-props)
+
```js
-import { compose, withState } from 'recompose'
-import { inspectProps } from 'react-inspect-props'
+import { compose, withState } from 'recompose';
+import { inspectProps } from 'react-inspect-props';
compose(
withState('count', 'setCount', 0),
inspectProps('Counter inspector')
-)(Counter)
+)(Counter);
```
#### Inspect React states
+
##### [`remotedev-react-state`](https://github.com/jhen0409/remotedev-react-state)
+
```js
import connectToDevTools from 'remotedev-react-state'
@@ -43,18 +50,22 @@ componentWillMount() {
```
#### Inspect React hooks (useState and useReducer)
+
##### [`reinspect`](https://github.com/troch/reinspect)
+
```js
-import { useState } from 'reinspect'
+import { useState } from 'reinspect';
export function CounterWithUseState({ id }) {
- const [count, setCount] = useState(0, id)
- // ...
+ const [count, setCount] = useState(0, id);
+ // ...
}
```
### [Mobx](https://github.com/mobxjs/mobx)
+
#### [`mobx-remotedev`](https://github.com/zalmoxisus/mobx-remotedev)
+
```js
import remotedev from 'mobx-remotedev';
// or import remotedev from 'mobx-remotedev/lib/dev'
@@ -66,14 +77,16 @@ const appStore = observable({
// Or
class appStore {
- // ...
+ // ...
}
export default remotedev(appStore);
-````
+```
### [Angular](https://github.com/angular/angular)
+
#### [ng2-redux](https://github.com/angular-redux/ng2-redux)
+
```js
import { NgReduxModule, NgRedux, DevToolsExtension } from 'ng2-redux';
@@ -101,9 +114,11 @@ import { NgReduxModule, NgRedux, DevToolsExtension } from 'ng2-redux';
}
}
```
+
For Angular 1 see [ng-redux](https://github.com/angular-redux/ng-redux).
#### [Angular @ngrx/store](https://ngrx.io/) + [`@ngrx/store-devtools`](https://ngrx.io/guide/store-devtools)
+
```js
import { StoreDevtoolsModule } from '@ngrx/store-devtools';
@@ -112,55 +127,71 @@ import { StoreDevtoolsModule } from '@ngrx/store-devtools';
StoreModule.forRoot(rootReducer),
// Instrumentation must be imported after importing StoreModule (config is optional)
StoreDevtoolsModule.instrument({
- maxAge: 5
- })
- ]
+ maxAge: 5,
+ }),
+ ],
})
-export class AppModule { }
+export class AppModule {}
```
[`Example of integration`](https://github.com/ngrx/platform/tree/master/projects/example-app/) ([live demo](https://ngrx.github.io/platform/example-app/)).
### [Ember](http://emberjs.com/)
+
#### [`ember-redux`](https://github.com/ember-redux/ember-redux)
+
```js
//app/enhancers/index.js
import { compose } from 'redux';
-var devtools = window.__REDUX_DEVTOOLS_EXTENSION__ ? window.__REDUX_DEVTOOLS_EXTENSION__() : f => f;
+var devtools = window.__REDUX_DEVTOOLS_EXTENSION__
+ ? window.__REDUX_DEVTOOLS_EXTENSION__()
+ : (f) => f;
export default compose(devtools);
```
### [Cycle](https://github.com/cyclejs/cyclejs)
-#### [`@culli/store`](https://github.com/milankinen/culli/tree/master/packages/store)
-```js
-import {run} from "@cycle/most-run"
-import {makeDOMDriver as DOM} from "@cycle/dom"
-import Store, {ReduxDevtools} from "@culli/store"
-import App, {newId} from "./App"
+#### [`@culli/store`](https://github.com/milankinen/culli/tree/master/packages/store)
+
+```js
+import { run } from '@cycle/most-run';
+import { makeDOMDriver as DOM } from '@cycle/dom';
+import Store, { ReduxDevtools } from '@culli/store';
+import App, { newId } from './App';
run(App, {
- DOM: DOM("#app"),
- Store: Store(ReduxDevtools({items: [{id: newId(), num: 0}, {id: newId(), num: 0}]}))
-})
+ DOM: DOM('#app'),
+ Store: Store(
+ ReduxDevtools({
+ items: [
+ { id: newId(), num: 0 },
+ { id: newId(), num: 0 },
+ ],
+ })
+ ),
+});
```
### [Freezer](https://github.com/arqex/freezer)
+
#### [`freezer-redux-devtools`](https://github.com/arqex/freezer-redux-devtools)
+
```js
import React, { Component } from 'react';
import { supportChromeExtension } from 'freezer-redux-devtools/freezer-redux-middleware';
import Freezer from 'freezer-js';
// Our state is a freezer object
-var State = new Freezer({hello: 'world'});
+var State = new Freezer({ hello: 'world' });
// Enable the extension
-supportChromeExtension( State );
+supportChromeExtension(State);
```
### [Horizon](https://github.com/rethinkdb/horizon)
+
#### [`horizon-remotedev`](https://github.com/zalmoxisus/horizon-remotedev)
+
```js
// import hzRemotedev from 'horizon-remotedev';
// or import hzRemotedev from 'horizon-remotedev/lib/dev'
@@ -171,11 +202,13 @@ const horizon = Horizon();
// ...
// Specify the horizon instance to monitor
-hzRemotedev(horizon("react_messages"))
+hzRemotedev(horizon('react_messages'));
```
### [Fable](https://github.com/fable-compiler/Fable)
+
#### [`fable-elmish/debugger`](https://github.com/fable-elmish/debugger)
+
```fsharp
open Elmish.Debug
@@ -196,18 +229,25 @@ Program.mkProgram init update view
```
### [PureScript](https://github.com/purescript/purescript)
+
#### [`purescript-react-redux`](https://github.com/ethul/purescript-react-redux)
+
[`Example of integration`](https://github.com/ethul/purescript-react-redux-example).
### [ClojureScript](https://github.com/clojure/clojurescript)
+
[`Example of integration`](http://gitlab.xet.ru:9999/publicpr/clojurescript-redux/tree/master#dev-setup)
### [Python](https://www.python.org/)
+
#### [`pyredux`](https://github.com/peterpeter5/pyredux)
+
[WIP](https://github.com/zalmoxisus/remotedev-server/issues/34)
### [Swift](https://github.com/apple/swift)
+
#### [`katanaMonitor`](https://github.com/bolismauro/katanaMonitor-lib-swift) for [`katana-swift`](https://github.com/BendingSpoons/katana-swift)
+
```swift
import KatanaMonitor
@@ -221,7 +261,9 @@ middleware.append(MonitorMiddleware.create(using: .defaultConfiguration))
```
### [Reductive](https://github.com/reasonml-community/reductive)
+
#### [`reductive-dev-tools`](https://github.com/ambientlight/reductive-dev-tools)
+
```reason
let storeEnhancer =
ReductiveDevTools.(
@@ -229,30 +271,32 @@ let storeEnhancer =
Extension.enhancerOptions(~name="MyApp", ()),
)
);
-
+
let storeCreator = storeEnhancer @@ Reductive.Store.create;
```
### [Aurelia](http://aurelia.io)
+
#### [`aurelia-store`](https://aurelia.io/docs/plugins/store)
+
```ts
import {Aurelia} from 'aurelia-framework';
import {initialState} from './state';
-
+
export function configure(aurelia: Aurelia) {
aurelia.use
.standardConfiguration()
.feature('resources');
-
+
...
-
+
aurelia.use.plugin('aurelia-store', {
initialState,
devToolsOptions: { // optional
... // see https://github.com/zalmoxisus/redux-devtools-extension/blob/master/docs/API/Arguments.md
},
});
-
+
aurelia.start().then(() => aurelia.setRoot());
}
```
diff --git a/extension/docs/README.md b/extension/docs/README.md
index f40b08be..f6df934a 100644
--- a/extension/docs/README.md
+++ b/extension/docs/README.md
@@ -1,21 +1,21 @@
# Documentation
-* [Extension](/README.md)
- * [Installation](/README.md#installation)
- * [Usage](/README.md#usage)
- * [Demo](/README.md#demo)
-* [API Reference](/docs/API/README.md)
- * [Options (arguments)](/docs/API/Arguments.md)
- * [Methods (advanced API)](/docs/API/Methods.md)
-* Features
- * [Trace actions calls](/docs/Features/Trace.md)
-* [Integrations](/docs/Integrations.md)
-* [FAQ](/docs/FAQ.md)
-* [Troubleshooting](/docs/Troubleshooting.md)
-* [Recipes](/docs/Recipes.md)
-* [Articles](/docs/Articles.md)
-* [Videos](/docs/Videos.md)
-* [Credits](/docs/Credits.md)
-* [Support us](/README.md#backers)
-* [Feedback](/docs/Feedback.md)
-* [Change Log](https://github.com/zalmoxisus/redux-devtools-extension/releases)
+- [Extension](/README.md)
+ - [Installation](/README.md#installation)
+ - [Usage](/README.md#usage)
+ - [Demo](/README.md#demo)
+- [API Reference](/docs/API/README.md)
+ - [Options (arguments)](/docs/API/Arguments.md)
+ - [Methods (advanced API)](/docs/API/Methods.md)
+- Features
+ - [Trace actions calls](/docs/Features/Trace.md)
+- [Integrations](/docs/Integrations.md)
+- [FAQ](/docs/FAQ.md)
+- [Troubleshooting](/docs/Troubleshooting.md)
+- [Recipes](/docs/Recipes.md)
+- [Articles](/docs/Articles.md)
+- [Videos](/docs/Videos.md)
+- [Credits](/docs/Credits.md)
+- [Support us](/README.md#backers)
+- [Feedback](/docs/Feedback.md)
+- [Change Log](https://github.com/zalmoxisus/redux-devtools-extension/releases)
diff --git a/extension/docs/Recipes.md b/extension/docs/Recipes.md
index eeb31653..5bc8e751 100644
--- a/extension/docs/Recipes.md
+++ b/extension/docs/Recipes.md
@@ -12,37 +12,42 @@ const store = createStore(
(window as any).__REDUX_DEVTOOLS_EXTENSION__()
);
```
+
Note that you many need to set `no-any` to false in your `tslint.json` file.
-Alternatively you can use typeguard in order to avoid
+Alternatively you can use typeguard in order to avoid
casting to any.
```typescript
-import { createStore, StoreEnhancer } from "redux";
-
-// ...
-
-type WindowWithDevTools = Window & {
- __REDUX_DEVTOOLS_EXTENSION__: () => StoreEnhancer
-}
-
-const isReduxDevtoolsExtenstionExist =
-(arg: Window | WindowWithDevTools):
- arg is WindowWithDevTools => {
- return '__REDUX_DEVTOOLS_EXTENSION__' in arg;
-}
+import { createStore, StoreEnhancer } from 'redux';
// ...
-const store = createStore(rootReducer, initialState,
- isReduxDevtoolsExtenstionExist(window) ?
- window.__REDUX_DEVTOOLS_EXTENSION__() : undefined)
+type WindowWithDevTools = Window & {
+ __REDUX_DEVTOOLS_EXTENSION__: () => StoreEnhancer;
+};
+
+const isReduxDevtoolsExtenstionExist = (
+ arg: Window | WindowWithDevTools
+): arg is WindowWithDevTools => {
+ return '__REDUX_DEVTOOLS_EXTENSION__' in arg;
+};
+
+// ...
+
+const store = createStore(
+ rootReducer,
+ initialState,
+ isReduxDevtoolsExtenstionExist(window)
+ ? window.__REDUX_DEVTOOLS_EXTENSION__()
+ : undefined
+);
```
### Export from browser console or from application
```js
-store.liftedStore.getState()
+store.liftedStore.getState();
```
The extension is not sharing `store` object, so you should take care of that.
@@ -55,16 +60,19 @@ We're [not allowing that from instrumentation part](https://github.com/zalmoxisu
import { createStore, compose } from 'redux';
import { devToolsEnhancer } from 'redux-devtools-extension/logOnly';
-const store = createStore(reducer, /* preloadedState, */ compose(
-devToolsEnhancer({
- instaceID: 1,
- name: 'Blacklisted',
- actionsBlacklist: '...'
-}),
-devToolsEnhancer({
- instaceID: 2,
- name: 'Whitelisted',
- actionsWhitelist: '...'
-})
-));
+const store = createStore(
+ reducer,
+ /* preloadedState, */ compose(
+ devToolsEnhancer({
+ instaceID: 1,
+ name: 'Blacklisted',
+ actionsBlacklist: '...',
+ }),
+ devToolsEnhancer({
+ instaceID: 2,
+ name: 'Whitelisted',
+ actionsWhitelist: '...',
+ })
+ )
+);
```
diff --git a/extension/docs/Troubleshooting.md b/extension/docs/Troubleshooting.md
index f7be9e5b..e3cf226f 100644
--- a/extension/docs/Troubleshooting.md
+++ b/extension/docs/Troubleshooting.md
@@ -6,7 +6,7 @@ Make sure you [applied the enhancer](https://github.com/zalmoxisus/redux-devtool
Don't mix the old Redux API with the new one. Pass enhancers and applyMiddleware as last createStore argument.
-### Access file url (`file:///`)
+### Access file url (`file:///`)
If you develop on your local filesystem, make sure to allow Redux DevTools access to `file:///` URLs in the settings of this extension:
@@ -18,18 +18,24 @@ Most likely you mutate the state. Check it by [adding `redux-immutable-state-inv
### @@INIT or REPLACE action resets the state of the app or last actions RE-APPLIED
-`@@redux/REPLACE` (or `@@INIT`) is used internally when the application is hot reloaded. When you use `store.replaceReducer` the effect will be the same as for hot-reloading, where the extension is recomputing all the history again. To avoid that set [`shouldHotReload`](/docs/API/Arguments.md#shouldhotreload) parameter to `false`.
+`@@redux/REPLACE` (or `@@INIT`) is used internally when the application is hot reloaded. When you use `store.replaceReducer` the effect will be the same as for hot-reloading, where the extension is recomputing all the history again. To avoid that set [`shouldHotReload`](/docs/API/Arguments.md#shouldhotreload) parameter to `false`.
-### It doesn't work with other store enhancers
+### It doesn't work with other store enhancers
Usually the extension's store enhancer should be last in the compose. When you're using [`window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__`](/README.md#12-advanced-store-setup) or [`composeWithDevTools`](/README.md#13-use-redux-devtools-extension-package-from-npm) helper you don't have to worry about the enhancers order. However some enhancers ([like `redux-batched-subscribe`](https://github.com/zalmoxisus/redux-devtools-extension/issues/261)) also have this requirement to be the last in the compose. In this case you can use it like so:
```js
-const store = createStore(reducer, preloadedState, compose(
- // applyMiddleware(thunk),
- window.__REDUX_DEVTOOLS_EXTENSION__ ? window.__REDUX_DEVTOOLS_EXTENSION__() : noop => noop,
- batchedSubscribe(/* ... */)
-));
+const store = createStore(
+ reducer,
+ preloadedState,
+ compose(
+ // applyMiddleware(thunk),
+ window.__REDUX_DEVTOOLS_EXTENSION__
+ ? window.__REDUX_DEVTOOLS_EXTENSION__()
+ : (noop) => noop,
+ batchedSubscribe(/* ... */)
+ )
+);
```
Where `batchedSubscribe` is `redux-batched-subscribe` store enhancer.
@@ -41,14 +47,19 @@ That is happening due to serialization of some huge objects included in the stat
You can do that by including/omitting data containing specific values, having specific types... In the example below we're omitting parts of action and state objects with the key `data` (in case of action only when was dispatched action `FILE_DOWNLOAD_SUCCESS`):
```js
-const actionSanitizer = (action) => (
- action.type === 'FILE_DOWNLOAD_SUCCESS' && action.data ?
- { ...action, data: '<>' } : action
+const actionSanitizer = (action) =>
+ action.type === 'FILE_DOWNLOAD_SUCCESS' && action.data
+ ? { ...action, data: '<>' }
+ : action;
+const store = createStore(
+ rootReducer,
+ window.__REDUX_DEVTOOLS_EXTENSION__ &&
+ window.__REDUX_DEVTOOLS_EXTENSION__({
+ actionSanitizer,
+ stateSanitizer: (state) =>
+ state.data ? { ...state, data: '<>' } : state,
+ })
);
-const store = createStore(rootReducer, window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__({
- actionSanitizer,
- stateSanitizer: (state) => state.data ? { ...state, data: '<>' } : state
-}));
```
There's a more advanced [example on how to implement that for `ui-router`](https://github.com/zalmoxisus/redux-devtools-extension/issues/455#issuecomment-404538385).
@@ -58,20 +69,21 @@ The extension is in different process and cannot access the store object directl
### It fails to serialize data when [passing synthetic events](https://github.com/zalmoxisus/redux-devtools-extension/issues/275) or [calling an action directly with `redux-actions`](https://github.com/zalmoxisus/redux-devtools-extension/issues/287)
React synthetic event cannot be reused for performance reason. So, it's not possible to serialize event objects you pass to action payloads.
-
+
1. The best solution is **not to pass the whole event object to reducers, but the data you need**:
- ```diff
- function click(event) {
- return {
- type: ELEMENT_CLICKED,
- - event: event
- + value: event.target.value
- };
- }
- ```
+
+```diff
+function click(event) {
+ return {
+ type: ELEMENT_CLICKED,
+- event: event
++ value: event.target.value
+ };
+}
+```
2. If you cannot pick data from the event object or, for some reason, you need the whole object, use `event.persist()` as suggested in [React Docs](https://facebook.github.io/react/docs/events.html#event-pooling), but it will consume RAM while not needed.
-
+
```diff
function increment(event) {
+ event.persist();
@@ -83,7 +95,7 @@ React synthetic event cannot be reused for performance reason. So, it's not poss
```
3. A workaround, to pass the whole object and at the same time not to persist it, is to override this key of the stringified payload in your action creator. Add a custom `toJSON` function right in the action object (which will be called by the extension before accessing the object):
-
+
```diff
function increment(event) {
return {
@@ -95,17 +107,23 @@ React synthetic event cannot be reused for performance reason. So, it's not poss
};
}
```
+
Note that it shouldn't be arrow function as we want to have access to the function's `this`.
-
+
As we don't have access to the original object, skipping and recomputing actions during hot reloading will not work in this case. We recommend to use the first solution whenever possible.
-### Symbols or other unserializable data not shown
+### Symbols or other unserializable data not shown
To get data which cannot be serialized by `JSON.stringify`, set [`serialize` parameter](/docs/API/Arguments.md#serialize):
+
```js
-const store = Redux.createStore(reducer, window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__({
- serialize: true
-}));
+const store = Redux.createStore(
+ reducer,
+ window.__REDUX_DEVTOOLS_EXTENSION__ &&
+ window.__REDUX_DEVTOOLS_EXTENSION__({
+ serialize: true,
+ })
+);
```
It will handle also date, regex, undefined, error objects, symbols, maps, sets and functions.
diff --git a/extension/examples/buildAll.js b/extension/examples/buildAll.js
index 72653ba1..3a558760 100644
--- a/extension/examples/buildAll.js
+++ b/extension/examples/buildAll.js
@@ -13,7 +13,7 @@ var exampleDirs = fs.readdirSync(__dirname).filter((file) => {
// Ordering is important here. `npm install` must come first.
var cmdArgs = [
{ cmd: 'npm', args: ['install'] },
- { cmd: 'webpack', args: ['index.js'] }
+ { cmd: 'webpack', args: ['index.js'] },
];
for (const dir of exampleDirs) {
@@ -21,7 +21,7 @@ for (const dir of exampleDirs) {
// declare opts in this scope to avoid https://github.com/joyent/node/issues/9158
const opts = {
cwd: path.join(__dirname, dir),
- stdio: 'inherit'
+ stdio: 'inherit',
};
let result = {};
if (process.platform === 'win32') {
diff --git a/extension/examples/counter/.babelrc b/extension/examples/counter/.babelrc
index 61058eb2..9b7d435a 100644
--- a/extension/examples/counter/.babelrc
+++ b/extension/examples/counter/.babelrc
@@ -1,3 +1,3 @@
{
- "presets": [ "es2015", "stage-0", "react" ]
+ "presets": ["es2015", "stage-0", "react"]
}
diff --git a/extension/examples/counter/actions/counter.js b/extension/examples/counter/actions/counter.js
index 9b864fd5..94fcdca1 100644
--- a/extension/examples/counter/actions/counter.js
+++ b/extension/examples/counter/actions/counter.js
@@ -5,18 +5,18 @@ let t;
export function increment() {
return {
- type: INCREMENT_COUNTER
+ type: INCREMENT_COUNTER,
};
}
export function decrement() {
return {
- type: DECREMENT_COUNTER
+ type: DECREMENT_COUNTER,
};
}
export function autoIncrement(delay = 10) {
- return dispatch => {
+ return (dispatch) => {
if (t) {
clearInterval(t);
t = undefined;
@@ -29,7 +29,7 @@ export function autoIncrement(delay = 10) {
}
export function incrementAsync(delay = 1000) {
- return dispatch => {
+ return (dispatch) => {
setTimeout(() => {
dispatch(increment());
}, delay);
diff --git a/extension/examples/counter/components/Counter.js b/extension/examples/counter/components/Counter.js
index 63372813..08a0fcdb 100644
--- a/extension/examples/counter/components/Counter.js
+++ b/extension/examples/counter/components/Counter.js
@@ -3,17 +3,18 @@ import PropTypes from 'prop-types';
class Counter extends Component {
render() {
- const { increment, autoIncrement, incrementAsync, decrement, counter } = this.props;
+ const {
+ increment,
+ autoIncrement,
+ incrementAsync,
+ decrement,
+ counter,
+ } = this.props;
return (