Redux DevTools extension.
replaceReducer
when shouldHotReload
is set to false
. @zalmoxisus #326ES2015 Maps/Sets
To handle these unserializable by JSON.stringify
data (and also dates, regexes, undefined, error objects, symbols and functions), set serialize
parameter:
const store = Redux.createStore(reducer, window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__({
serialize: true
}));
ES Symbols lose their identity after importing, persisting..., but at least global symbols (Symbol.for
) can be safely retained. Thanks to @Velenir for implementing this.
Revert stringifying Symbols out of the box as not being reliable in case of constructors.
Now it's possible to restrict restrict the extension, just specify the features you allow:
const composeEnhancers = composeWithDevTools({
features: {
pause: true, // start/pause recording of dispatched actions
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
dispatch: true, // dispatch custom actions or action creators
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.
It's useful to include the extension in production as well. See the blog post for more details.
If you want to restrict it there, use redux-devtools-extension/logOnlyInProduction
:
import { createStore } from 'redux';
import { devToolsEnhancer } from 'redux-devtools-extension/logOnlyInProduction';
const store = createStore(reducer, /* preloadedState, */ devToolsEnhancer(
// options like actionSanitizer, stateSanitizer
));
or with middlewares and enhancers:
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). If you usereact-create-app
, it already does it for you.
If you're already checking process.env.NODE_ENV
when creating the store, include redux-devtools-extension/logOnly
for production enviroment.
autoPause
, filter
, serialize
, latency
, stateSanitizer
, actionSanitizer
See API reference for more details.
Now you can persist, import, and investigate ImmutableJS data:
Just pass the Immutable library to the new serialize
parameter like so:
import Immutable from 'immutable';
// ...
const store = createStore(rootReducer, window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__({
serialize: {
immutable: Immutable
}
}));
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:
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]
}
}));
serialize
parameter and deprecationsWe're deprecating (de)serializeState
/ (de)serializeAction
parameters in favour of the new one:
serialize (object) - contains { replacer: function, reviver: function, options: object/boolean, refs: array }
replacer function(key, value)
- JSON replacer
function used for both actions and states stringify.
reviver function(key, value)
- JSON reviver
function used for parsing the imported actions and states.
options object or boolean
:
undefined
- use regular JSON.stringify
to send data - the fast mode.false
- handle only circular references.true
- handle also dates, regexes, undefined, error objects, symbols, and functions.date
, regex
, undefined
, error
, and function
keys. Fo each of them you can indicate whether to include (if set as true
). For function
key you can also specify a custom function which handles serialization. See jsan
for more details. Example:const store = Redux.createStore(reducer, window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__({
serialize: {
options: {
undefined: true,
function: function(fn) { return fn.toString() }
}
}
}));
Example of usage with mori data structures:
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
}
}));
File an issue if you still need deSerializeState
/ deSerializeAction
, which were getting the whole root state / action payload, instead of (key, value)
.
getActionType
callback parameterIf you're using the extension for non-redux apps, now you can specify what will be shown in the monitors:
window.__REDUX_DEVTOOLS_EXTENSION__.connect({ getActionType: (a) => a.Case })
See https://github.com/fable-compiler/fable-elmish/issues/18 for details.
Just drag and drop specific actions. It will help to check weird race conditions as stated here and also to better debug features.
Hold shift
key while toggling actions:
By toggling the Persist
button, the states won't be removed from the monitor on unloading the page and will be restored on reload:
disconnect
method (#272).getMonitor
parameterIn 2.3
we've introduced a method to expose the monitors API (see the release details). The purpose was to let users know when it is dispatched a monitor action or moving back and forth. So one can prevent side effects when time travelling or cancelling actions (see #86, #145, https://github.com/gaearon/redux-devtools/issues/167).
However, in 2.7
we added a better solution, to lock all the changes (see the post for details). So, we're deprecating getMonitor
parameter, which is not necessary anymore. In case you still have a reason to use it, please open an issue.
Chart and Inspector monitors are combined now. Just click on the node and get detailed tree view. Also now you can see states, actions and diffs as raw data, which can be expanded as a tree as well.