use-travel
                                
                                 use-travel copied to clipboard
                                
                                    use-travel copied to clipboard
                            
                            
                            
                        A React hook for state time travel with undo, redo, reset and archive functionalities.
use-travel
A React hook for state time travel with undo, redo, reset and archive functionalities.
Motivation
use-travel is a small and high-performance library for state time travel. It's built on Mutative to support mutation updating immutable data. It's designed to be simple and easy to use, and it's also customizable for different use cases.
It's suitable for building any time travel feature in your application.
Installation
npm install use-travel mutative
# or
yarn add use-travel mutative
Features
- Undo/Redo/Reset/Go/Archive functionalities
- Mutations update immutable data
- Small size for time travel with Patches history
- Customizable history size
- Customizable initial patches
- High performance
- Mark function for custom immutability
Example
API
You can use useTravel to create a time travel state. And it returns a tuple with the current state, the state setter, and the controls. The controls include back(), forward(), reset(), canBack(), canForward(), canArchive(), getHistory(), patches, position, archive(), and go().
import { useTravel } from 'use-travel';
const App = () => {
  const [state, setState, controls] = useTravel(0, {
    maxHistory: 10,
    initialPatches: {
      patches: [],
      inversePatches: [],
    },
  });
  return (
    <div>
      <div>{state}</div>
      <button onClick={() => setState(state + 1)}>Increment</button>
      <button onClick={() => setState(state - 1)}>Decrement</button>
      <button onClick={() => controls.back()} disabled={!controls.canBack()}>
        Undo
      </button>
      <button
        onClick={() => controls.forward()}
        disabled={!controls.canForward()}
      >
        Redo
      </button>
      <button onClick={controls.reset}>Reset</button>
      {controls.getHistory().map((state, index) => (
        <div key={index}>{state}</div>
      ))}
      {controls.patches.patches.map((patch, index) => (
        <div key={index}>{JSON.stringify(patch)}</div>
      ))}
      <div>{controls.position}</div>
      <button
        onClick={() => {
          controls.go(1);
        }}
      >
        Go
      </button>
    </div>
  );
};
Parameters
| Parameter | type | description | default | 
|---|---|---|---|
| maxHistory | number | The maximum number of history to keep | 10 | 
| initialPatches | TravelPatches | The initial patches | {patches: [],inversePatches: []} | 
| initialPosition | number | The initial position of the state | 0 | 
| autoArchive | boolean | Auto archive the state | true | 
Returns
| Return | type | description | 
|---|---|---|
| state | Value<S, F> | The current state | 
| setState | Updater<InitialValue<S>> | The state setter, support mutation update or return immutable data | 
| controls.back | (amount?: number) => void | Go back to the previous state | 
| controls.forward | (amount?: number) => void | Go forward to the next state | 
| controls.reset | () => void | Reset the state to the initial state | 
| controls.canBack | () => boolean | Check if can go back to the previous state | 
| controls.canForward | () => boolean | Check if can go forward to the next state | 
| controls.canArchive | () => boolean | Check if can archive the current state | 
| controls.getHistory | () => T[] | Get the history of the state | 
| controls.patches | TravelPatches[] | Get the patches history of the state | 
| controls.position | number | Get the current position of the state | 
| controls.go | (nextPosition: number) => void | Go to the specific position of the state | 
| controls.archive | () => void | Archive the current state(the autoArchiveoptions should befalse) | 
TravelPatchesis the type of patches history, it includespatchesandinversePatches.
If you want to control the state travel manually, you can set the
autoArchiveoption tofalse, and use thecontrols.archivefunction to archive the state.
If you want to persist the state, you can use
state/controls.patches/controls.positionto save the travel history. Then, read the persistent data asinitialState,initialPatches, andinitialPositionwhen initializing the state, like this:
const [state, setState, controls] = useTravel(initialState, {
  initialPatches,
  initialPosition,
});
License
use-travel is MIT licensed.