Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/homerchen19/use-undo

React Hooks to implement Undo and Redo functionality
https://github.com/homerchen19/use-undo

hooks react react-hooks

Last synced: 2 months ago
JSON representation

React Hooks to implement Undo and Redo functionality

Awesome Lists containing this project

README

        

# ♻️ use-undo

undo/redo functionality with React [Hooks](https://reactjs.org/docs/hooks-intro.html).





screensho

## Installation

```sh
yarn add use-undo
```

## Usage

[![Edit use-undo-demo](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/use-undo-demo-hifeo?fontsize=14&hidenavigation=1&theme=dark&view=editor)

```js
import React from 'react';
import ReactDOM from 'react-dom';
import useUndo from 'use-undo';

const App = () => {
const [
countState,
{
set: setCount,
reset: resetCount,
undo: undoCount,
redo: redoCount,
canUndo,
canRedo,
},
] = useUndo(0);
const { present: presentCount } = countState;

return (


You clicked {presentCount} times


setCount(presentCount + 1)}>
+

setCount(presentCount - 1)}>
-


undo


redo

resetCount(0)}>
reset to 0


);
};
```

## Manual Checkpoints

Manual checkpoints are helpful also when you want manual control over checkpoints. For example it is more helpful when you want to handle input type html tag where value needs to be handled alongside the undo and redo functionality should be handled over some conditions.

```js
import React from 'react';
import ReactDOM from 'react-dom';
import useUndo from 'use-undo';

const App = () => {
const [
countState,
{
set: setCount,
reset: resetCount,
undo: undoCount,
redo: redoCount,
canUndo,
canRedo,
},
] = useUndo(0, { useCheckpoints: true });
const { present: presentCount } = countState;

return (


You clicked {presentCount} times


setCount(presentCount + 1, true)}>
WithCheckpoint+

setCount(presentCount - 1, true)}>
WithCheckpoint-

setCount(presentCount + 1)}>
NoCheckpoint+

setCount(presentCount - 1)}>
NoCheckpoint-


undo


redo

resetCount(0)}>
reset to 0


);
};
```

## API

### useUndo

```js
const [state, actions] = useUndo(initialState);
```

#### state

##### Type: `Object`

| Key | Type | Description |
| ------- | :-----: | ------------------ |
| past | `Array` | The undo stack. |
| present | `Any` | The present state. |
| future | `Array` | The redo stack. |

#### actions

##### Type: `Object`

| Key | Type | Description |
| ------- | :--------: | ------------------------------------------------------------------------------------------ |
| set | `function` | Assign a new value to `present`. |
| reset | `function` | Clear `past` array and `future` array. Assign a new value to `present`. |
| undo | `function` | See [handling-undo](https://redux.js.org/recipes/implementing-undo-history#handling-undo). |
| redo | `function` | See [handling-redo](https://redux.js.org/recipes/implementing-undo-history#handling-redo). |
| canUndo | `boolean` | Check whether `state.undo.length` is `0`. |
| canRedo | `boolean` | Check whether `state.redo.length` is `0`. |

## How does it work?

Refer to [_Redux Implementing Undo History_](hhttps://redux.js.org/recipes/implementing-undo-history), `use-undo` implements the same concect with [`useReducer`](https://reactjs.org/docs/hooks-reference.html#usereducer).
The state structure looks like:

```js
{
past: Array,
present: ,
future: Array
}
```

It stores all states we need. To operate on this state, there are three functions in [`actions`](#actions) (`set`, `undo` and `redo`) that dispatch defined types and necessary value.

## Related repo

- [omnidan/redux-undo](https://github.com/omnidan/redux-undo)

## License

MIT © [homerchen19](https://github.com/homerchen19)