All Projects → inakianduaga → redux-state-history

inakianduaga / redux-state-history

Licence: MIT license
Redux store enhancers for tracking and visualizing state changes

Programming Languages

typescript
32286 projects
javascript
184084 projects - #8 most used programming language

Projects that are alternatives of or similar to redux-state-history

StarWarsSearch-MVI
Star wars sample android project showcasing the use of View components for rendering UI in Fragments and Activities. Uses Android Jetpack, clean architecture with MVI (Uni-directional data flow), dagger hilt, and kotlin coroutines with StateFlow
Stars: ✭ 189 (+105.43%)
Mutual labels:  redux-store
superglue
A productive library for Classic Rails, React and Redux
Stars: ✭ 106 (+15.22%)
Mutual labels:  redux-store
React on rails
Integration of React + Webpack + Rails + rails/webpacker including server-side rendering of React, enabling a better developer experience and faster client performance.
Stars: ✭ 4,815 (+5133.7%)
Mutual labels:  redux-store
flutter redux
A Flutter Starter Application
Stars: ✭ 25 (-72.83%)
Mutual labels:  redux-store
next-react-boilerplate
🔥 NextJS with additional tech feature like react-boilerplate. Demo >>
Stars: ✭ 20 (-78.26%)
Mutual labels:  redux-store
redux-storage
Persistence layer for redux with flexible backends
Stars: ✭ 218 (+136.96%)
Mutual labels:  redux-store
ReduxSimple
Simple Stupid Redux Store using Reactive Extensions
Stars: ✭ 119 (+29.35%)
Mutual labels:  redux-store

Redux State History

Build Status

Redux store enhancers / component for tracking and visualizing state changes & debugging remote sessions.

Inspired by the redux devtools and redux slider monitor, this package provides state recording/playback (i.e. "time travel") abilities for redux applications.

DEMO

Features:

  • Record state history efficiently locally / on production: Only state diffs are stored for each state change (performance untested for large state/long running applications).
  • Decoupled recording/debugging code: On production include only recording store enhancer for small footprint. Locally, use additional debug slider component to navigate/interact with the history.
  • Import/Export histories: Play them back locally, including realtime speed.
  • Time-travel is "pure": That is, state history changes without refiring the actual actions that produced said change (so still works for impure/async actions).

State history tracker:

A store enhancer provides the history tracking on each state change, recording the state change, the timestamp of the change, and the action type that produced said change. This is independent of the debug slider and can be used in production, requiring minimum dependencies (~16kb gzipped).

  • The actual state history is stored in the redux store under .stateHistory key.

Installation:

The state history tracker is installed as a store enhancer, in the same way other redux store enhancers like applyMiddleware, or the redux devtools are added. For example

import { createStore, applyMiddleware, compose } from 'redux';
import rootReducer from '../reducers/index';
import DevTools from '../containers/DevTools.tsx';
import thunk from 'redux-thunk';
let createHistory = require('history/lib/createHashHistory');
let createLogger = require('redux-logger');
let { syncReduxAndRouter } = require('redux-simple-router');
import trackHistory from 'redux-state-history/lib/stateHistory'; // THIS INCLUDES ONLY STATE HISTORY TRACKING FOR PROUCTION

const finalCreateStore = compose(
  applyMiddleware(thunk),
  applyMiddleware(createLogger()),
  trackHistory(),                              // STATE HISTORY STORE ENHANCER (DO NOT INCLUDE ON PRODUCTION)
  DevTools.instrument(),
)(createStore);

export const history = createHistory();

export default function configureStore() {
  const store = finalCreateStore(rootReducer);
  syncReduxAndRouter(history, store);

  return store;
}

Dev slider tool

This component provides state history interactivity, plus allows importing and exporting state sessions.

Installation:

Store enhancer:

The debug component needs a store enhancer to work (it uses it to replace the current state by whichever state is selected from the history, so needs root-level access). To install it, you follow the same logic as the state history tracker above

// ... imports
import { Devtool as debugStateHistory, trackHistory } from 'redux-state-history'; // THIS BUNDLE INCLUDES EVERYTHING, USE ONLY ON DEV

// ...
const finalCreateStore = compose(
  debugStateHistory,                          // STATE HISTORY DEV TOOLS STORE ENHANCER
  applyMiddleware(thunk),
  applyMiddleware(createLogger()),
  trackHistory()                              // STATE HISTORY STORE ENHANCER
  DevTools.instrument()
)(createStore);
// ...

Component

You can include the StateHistoryDevTool component anywhere in your application as long as you provide the store.stateHistory properties. For example, in your root component, you can do

import * as React from 'react';
import { Provider } from 'react-redux';
import  from './Component.tsx';
import Routes from '../routes.tsx';
import { Router } from 'react-router';
import { history } from '../store/configureStore.dev';
import { Component as StateHistoryDevTool } from 'redux-state-history'; // IMPORTS STATE HISTORY DEBUG COMPONENT

type IRootProps = {
  store: any
}

export default class Root extends React.Component<IRootProps, any> {
  public render() {
    const { store } = this.props;
    return (
        <Provider store={store}>
          <div>
            <Router history={ history }>
              { Routes }
            </Router>
            <StateHistoryDevTool { ...store.stateHistory } /> {/* Place anywhere you like */}
          </div>
        </Provider>
    );
  }
};

Supress build warnings:

Due to a jsondiffpatch library issue, the following has to be added to the webpack config to prevent warnings during build

  module: {
      exprContextCritical: false, // To disable jsondiff warning
  }

Note: On Combine Reducers:

If you use redux's combineReducers to set up your root reducer, you need to add a dummy "identity" reducer under the stateHistory key, otherwise the combinedReducers function will complain about that key not being predefined and drop it from the state.

const rootReducer = combineReducers({
  key: someReducer,
  key2: anotherReducer,
  ...
  stateHistory: (state = {}, action) => state, // dummy identity reducer to prevent combineReducers checks from throwing error
});
Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].