Skip to content

Commit 0facdbb

Browse files
committed
add maxAge option
1 parent 86f522a commit 0facdbb

File tree

3 files changed

+55
-7
lines changed

3 files changed

+55
-7
lines changed

src/createDevTools.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,6 @@ export default function createDevTools(children) {
77
const monitorProps = monitorElement.props;
88
const Monitor = monitorElement.type;
99
const ConnectedMonitor = connect(state => state)(Monitor);
10-
const enhancer = instrument((state, action) =>
11-
Monitor.update(monitorProps, state, action)
12-
);
1310

1411
return class DevTools extends Component {
1512
static contextTypes = {
@@ -20,7 +17,10 @@ export default function createDevTools(children) {
2017
store: PropTypes.object
2118
};
2219

23-
static instrument = () => enhancer;
20+
static instrument = (options) => instrument(
21+
(state, action) => Monitor.update(monitorProps, state, action),
22+
options
23+
);
2424

2525
constructor(props, context) {
2626
super(props, context);

src/instrument.js

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ function liftAction(action) {
138138
/**
139139
* Creates a history state reducer from an app's reducer.
140140
*/
141-
function liftReducerWith(reducer, initialCommittedState, monitorReducer) {
141+
function liftReducerWith(reducer, initialCommittedState, monitorReducer, options) {
142142
const initialLiftedState = {
143143
monitorState: monitorReducer(undefined, {}),
144144
nextActionId: 1,
@@ -235,6 +235,14 @@ function liftReducerWith(reducer, initialCommittedState, monitorReducer) {
235235
break;
236236
}
237237
case ActionTypes.PERFORM_ACTION: {
238+
if (options.maxAge && stagedActionIds.length === options.maxAge) {
239+
// If maxAge has been reached, remove oldest action
240+
delete actionsById[stagedActionIds[0]];
241+
skippedActionIds = skippedActionIds.filter(id => id !== stagedActionIds[0]);
242+
stagedActionIds = stagedActionIds.slice(1);
243+
committedState = computedStates[1].state;
244+
computedStates = computedStates.slice(1);
245+
}
238246
if (currentStateIndex === stagedActionIds.length - 1) {
239247
currentStateIndex++;
240248
}
@@ -339,7 +347,9 @@ function unliftStore(liftedStore, liftReducer) {
339347
/**
340348
* Redux instrumentation store enhancer.
341349
*/
342-
export default function instrument(monitorReducer = () => null) {
350+
export default function instrument(monitorReducer, options = {}) {
351+
if (!monitorReducer) { monitorReducer = () => null; }
352+
343353
return createStore => (reducer, initialState, enhancer) => {
344354

345355
function liftReducer(r) {
@@ -354,7 +364,7 @@ export default function instrument(monitorReducer = () => null) {
354364
}
355365
throw new Error('Expected the reducer to be a function.');
356366
}
357-
return liftReducerWith(r, initialState, monitorReducer);
367+
return liftReducerWith(r, initialState, monitorReducer, options);
358368
}
359369

360370
const liftedStore = createStore(liftReducer(reducer), enhancer);

test/instrument.spec.js

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,44 @@ describe('instrument', () => {
295295
expect(monitoredLiftedStore.getState().computedStates).toBe(savedComputedStates);
296296
});
297297

298+
describe('maxAge option', () => {
299+
let configuredStore;
300+
let configuredLiftedStore;
301+
302+
beforeEach(() => {
303+
configuredStore = createStore(counter, instrument(null, { maxAge: 2 }));
304+
configuredLiftedStore = configuredStore.liftedStore;
305+
});
306+
307+
it('should remove earliest action when maxAge is reached', () => {
308+
configuredStore.dispatch({ type: 'INCREMENT' });
309+
let liftedStoreState = configuredLiftedStore.getState();
310+
311+
expect(configuredStore.getState()).toBe(1);
312+
expect(Object.keys(liftedStoreState.actionsById).length).toBe(2);
313+
expect(liftedStoreState.committedState).toBe(undefined);
314+
315+
configuredStore.dispatch({ type: 'INCREMENT' });
316+
liftedStoreState = configuredLiftedStore.getState();
317+
318+
expect(configuredStore.getState()).toBe(2);
319+
expect(Object.keys(liftedStoreState.actionsById).length).toBe(2);
320+
expect(liftedStoreState.stagedActionIds).toExclude(0);
321+
expect(liftedStoreState.computedStates[0].state).toBe(1);
322+
expect(liftedStoreState.committedState).toBe(1);
323+
expect(liftedStoreState.currentStateIndex).toBe(1);
324+
});
325+
326+
it('should handle skipped actions', () => {
327+
configuredStore.dispatch({ type: 'INCREMENT' });
328+
configuredLiftedStore.dispatch(ActionCreators.toggleAction(1));
329+
configuredStore.dispatch({ type: 'INCREMENT' });
330+
expect(configuredLiftedStore.getState().skippedActionIds).toInclude(1);
331+
configuredStore.dispatch({ type: 'INCREMENT' });
332+
expect(configuredLiftedStore.getState().skippedActionIds).toExclude(1);
333+
});
334+
});
335+
298336
describe('Import State', () => {
299337
let monitoredStore;
300338
let monitoredLiftedStore;

0 commit comments

Comments
 (0)