Skip to content

Time travel #113

Closed
Closed
@gaearon

Description

@gaearon

Reviving musings from #6, I'm going to post my progress on working on time travel & other devtool goodness here.

screen shot 2015-06-17 at 02 00 47

I have a working proof of concept of time travel that uses the default dispatcher and relies on store composition to keep a log of state. This is not feature-complete (only “jumping to state #N” is supported), but shows how to implement such functionality with Store composition:

export const StateKeys = {
  LOG: Symbol('Log')
};

export const ActionTypes = {
  JUMP_TO_STATE: Symbol('JUMP_TO_STATE')
};

export default function recorder(store) {
  return function Recorder(state = {}, action) {
    let { [StateKeys.LOG]: log = [], ...atom } = state;

    let nextAtom;
    switch (action.type) {
    case ActionTypes.JUMP_TO_STATE:
      const { index } = action;
      nextAtom = log[index].nextAtom;
      break;
    default:
      nextAtom = store(atom, action);
      break;
    }

    log = [...log, {
      action,
      atom,
      nextAtom
    }];

    return {
      [StateKeys.LOG]: log,
      ...nextAtom
    };
  }
}

Usage:

const store = composeStores(stores);
const dispatcher = createDispatcher(recorder(store)); // wrap the store
const redux = createRedux(dispatcher);

This relies on the root atom being “normal” a JS object though. I think we'll need to store it internally as atom field instead inside a plain JS object created by us to support such “hidden” tool state.

I'd accept a PR that hides the user store's state inside an atom field on the Redux instance's state object, at the same time preserving the current API and behavior exactly. Redux.getState() should keep retuning that atom. Any other fields on the internal state will be assumed to be only used by the devtools.

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions