Skip to content

Commit f56f83a

Browse files
authored
Merge pull request #247 from omnidan/documentation
Documentation for stable release 1.0
2 parents 9e8b393 + 35c5d42 commit f56f83a

File tree

7 files changed

+321
-11
lines changed

7 files changed

+321
-11
lines changed

.github/ISSUE_TEMPLATE.md

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<!-- Source: https://github.com/stevemao/github-issue-templates/tree/master/conversational -->
2+
3+
**Note: for support questions, please ask questions on the gitter chat**. This repository's issues are reserved for feature requests and bug reports. Visit the gitter chat [here](https://gitter.im/omnidan/redux-undo).
4+
5+
* **I'm submitting a ...**
6+
- [ ] bug report
7+
- [ ] feature request
8+
- [ ] support request => Please do not submit support request here, see note at the top of this template.
9+
10+
* **What is the current behavior?**
11+
12+
13+
14+
* **What is the expected/desired behavior?**
15+
16+
17+
18+
* **If this is a feature request, what is the use case for changing the behavior?**
19+
20+
21+
22+
* **If the current behavior is a bug, please provide the steps to reproduce and if possible a minimal demo of the problem via a gist or similar.**
23+
24+
25+
26+
* **Please tell us about your environment:**
27+
28+
- Library version: 1.0.0
29+
- Redux version: 4.0.0
30+
- Browser: [all | Chrome XX | Firefox XX | IE XX | Safari XX | Edge XX]
31+
- Language: [all | TypeScript X.X | ES6/7 | ES5]
32+
33+
34+
* **Other information**
35+
36+
(e.g. detailed explanation, stacktraces, related issues, suggestions how to fix, links for us to have context, eg. stackoverflow, gitter, etc)
37+
38+

.github/PULL_REQUEST_TEMPLATE.md

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<!-- Source: https://github.com/stevemao/github-issue-templates/tree/master/conversational -->
2+
3+
* **Please check if the PR fulfills these requirements**
4+
- [ ] The commit message(s) are descriptive of the changes made
5+
- [ ] The PR contains changes that are focused and differs from other PRs
6+
- For bug fixes or features:
7+
- [ ] Tests for the changes have been added where needed
8+
- [ ] Docs have been added / updated
9+
10+
11+
* **What kind of change does this PR introduce?** (Bug fix, feature, docs update, ...)
12+
13+
14+
<!-- If this is a simple doc change, remove the following lines -->
15+
16+
17+
* **What is the current behavior?** (You can also link to an open issue here)
18+
19+
20+
21+
* **What is the new behavior (if this is a feature change)?**
22+
23+
24+
25+
* **Does this PR introduce a breaking change?** (What changes might users need to make in their application due to this PR?)
26+
27+
28+
29+
* **Other information**:
30+
31+

README.md

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,18 @@ _simple undo/redo functionality for redux state containers_
88

99
**Protip:** Check out the [todos-with-undo example](https://github.com/omnidan/redux-undo/tree/master/examples/todos-with-undo) or the [redux-undo-boilerplate](https://github.com/omnidan/redux-undo-boilerplate) to quickly get started with `redux-undo`.
1010

11-
**Switching from 0.x to 1.0 (beta):** Make sure to update your programs to the [latest History API](#history-api).
11+
**Switching from 0.x to 1.0:** Make sure to update your programs to the [latest History API](#history-api).
1212

1313
**Help wanted:** We are looking for volunteers to maintain this project, if you are interested, feel free to contact me at [[email protected]](mailto:[email protected])
1414

1515
---
1616

17-
**This README is about the new 1.0-beta branch of redux-undo, if you are using
17+
**This README is about the new 1.0 branch of redux-undo, if you are using
1818
or plan on using 0.6, check out [the `0.6` branch](https://github.com/omnidan/redux-undo/tree/0.6)**
1919

2020
---
2121

22-
## Note on 1.0.0-beta7
22+
## Note on Imports
2323

2424
If you use Redux Undo in CommonJS environment, **don’t forget to add `.default` to your import**.
2525

@@ -45,7 +45,7 @@ var ReduxUndo = window.ReduxUndo.default;
4545
## Installation
4646

4747
```
48-
npm install --save redux-undo@beta
48+
npm install --save redux-undo
4949
```
5050

5151

@@ -89,7 +89,7 @@ A [configuration](#configuration) can be passed like this:
8989
```js
9090
combineReducers({
9191
counter: undoable(counter, {
92-
limit: 10 // set a limit for the history
92+
limit: 10 // set a limit for the size of the history
9393
})
9494
})
9595
```
@@ -152,6 +152,8 @@ Now you can get your current state like this: `state.present`
152152

153153
And you can access all past states (e.g. to show a history) like this: `state.past`
154154

155+
**Note:** Your reducer still receives the current state, a.k.a. `state.present`. Therefore, you would not have to update an existing reducer to add undo functionality.
156+
155157

156158
## Undo/Redo Actions
157159

@@ -174,7 +176,7 @@ store.dispatch(ActionCreators.jump(5)) // redo 5 steps
174176
store.dispatch(ActionCreators.jumpToPast(index)) // jump to requested index in the past[] array
175177
store.dispatch(ActionCreators.jumpToFuture(index)) // jump to requested index in the future[] array
176178

177-
store.dispatch(ActionCreators.clearHistory()) // [beta only] Remove all items from past[] and future[] arrays
179+
store.dispatch(ActionCreators.clearHistory()) // Remove all items from past[] and future[] arrays
178180
```
179181

180182

@@ -198,7 +200,7 @@ undoable(reducer, {
198200
jumpToPastType: ActionTypes.JUMP_TO_PAST, // define custom action type for this jumpToPast action
199201
jumpToFutureType: ActionTypes.JUMP_TO_FUTURE, // define custom action type for this jumpToFuture action
200202

201-
clearHistoryType: ActionTypes.CLEAR_HISTORY, // [beta only] define custom action type for this clearHistory action
203+
clearHistoryType: ActionTypes.CLEAR_HISTORY, // define custom action type for this clearHistory action
202204
// you can also pass an array of strings to define several action types that would clear the history
203205
// beware: those actions will not be passed down to the wrapped reducers
204206

@@ -403,6 +405,8 @@ Have a read of the [Implementing Undo History recipe](https://redux.js.org/recip
403405

404406
If you have a question or just want to discuss something with other redux-undo users/maintainers, [chat with the community on gitter.im/omnidan/redux-undo](https://gitter.im/omnidan/redux-undo)
405407

408+
Also, look at the documentation over at [redux-undo.js.org](https://redux-undo.js.org/).
409+
406410
## License
407411

408412
MIT, see `LICENSE.md` for more information.

docs/FAQ.md

Lines changed: 143 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,145 @@
11
# FAQ
22

3-
Work-in-progress - check back later :)
3+
### Table of Contents
4+
5+
- [Where can I get help using `redux-undo`?](#where-can-I-get-help-using-redux-undo)
6+
- [Where can I find examples of how to use `redux-undo`?](#where-can-i-find-examples-of-how-to-use-redux-undo)
7+
- [How do I prevent cluttering up history with rapidly changing state?](#how-do-I-prevent-cluttering-up-history-with-rapidly-changing-state)
8+
- [Can I have multiple, separate undoable functions?](#can-i-have-multiple-separate-undoable-functions)
9+
- [Why are my actions not being filtered?](#why-are-my-actions-not-being-filtered)
10+
- [What is `_latestUnfiltered`? Can I remove it?](#what-is-_latestUnfiltered-can-i-remove-it)
11+
- [Why am I getting `Cannot find module 'redux-undo'`?](#why-am-i-getting-cannot-find-module-redux-undo)
12+
- [How do I set an initial state/history?](upgrading-to-1.0.md#initialstate)
13+
- [How do I upgrade from 0.X to 1.0?](upgrading-to-1.0.md)
14+
15+
## Where can I get help using `redux-undo`?
16+
17+
To get an understanding of the basics, read through the [README](/README.md) and checkout some [examples](#where-can-i-find-examples-of-how-to-use-redux-undo).
18+
19+
To get help with a specific use case, see if there is already an example in these docs or the examples. If not, ask for help in the [gitter chat](https://gitter.im/omnidan/redux-undo)!
20+
21+
If it seems you have found a bug or you are itching for a new feature, go ahead and submit it as an issue following the template provided. Please reserve Github issues for bugs and features **only**. Ask any other questions on the gitter chat and someone will probably be able to help you with your problem.
22+
23+
## Where can I find examples of how to use `redux-undo`?
24+
25+
Look at the `examples/` directory of the project folder. The `todos-with-undo/` is a good project to start messing with.
26+
27+
```sh
28+
$ git clone https://github.com/omnidan/redux-undo.git
29+
$ cd redux-undo/examples/todos-with-undo
30+
$ npm install
31+
$ npm start
32+
```
33+
34+
Just open http://localhost:3000 and you are good to go!
35+
36+
## How do I prevent cluttering up history with rapidly changing state?
37+
38+
The `throttled-drag/` project found the `examples/` directory gives a good demonstration of how to debounce undos (the filter is in `util/undoFilter.js`).
39+
40+
This general question has different solutions depending on your exact problem. Let's say you have one or more rapidly dispatched actions, for example `MOVE_CURSOR` and `UPDATE_OBJECT_POS`, that ends with a lone action `PLACE_OBJECT`, and you only want to record the end state after `PLACE_OBJECT`. Then you can simply use a filter `excludeAction(['MOVE_CURSOR', 'UPDATE_OBJECT_POS'])`
41+
42+
For more complex requirements, consider writing your own [custom filter](https://github.com/omnidan/redux-undo#custom-filters).
43+
44+
## Can I have multiple, separate undoable functions?
45+
46+
Yes you can! Simply wrap each reducer with its own `undoable()`.
47+
48+
```js
49+
const rootReducer = combineReducers({
50+
someData: undoable(dataReducer),
51+
otherData: undoable(otherDataReducer)
52+
});
53+
```
54+
55+
Do not forget to setup different undo/redo types to undo/redo each slice separately.
56+
57+
```js
58+
someData: undoable(dataReducer, {
59+
undoType: "DATA_UNDO",
60+
redoType: "DATA_REDO"
61+
// There is also jumpType, jumpToPastType, jumpToFutureType, clearHistoryType, and initTypes (which is an array of action types)
62+
});
63+
```
64+
65+
If you wish to have a single conglomerate history that a user can undo one action at a time, you can wrap the root reducer with `undoable()`.
66+
67+
```js
68+
const rootReducer = undoable(
69+
combineReducers({
70+
someData: dataReducer,
71+
otherData: otherDataReducer
72+
}),
73+
{...options...}
74+
);
75+
```
76+
77+
You probably need to use [custom filters](https://github.com/omnidan/redux-undo#custom-filters) and/or [`groupBy`](https://github.com/omnidan/redux-undo#grouping-actions) to undo/redo in reasonable chunks.
78+
79+
## Why are my actions not being filtered?
80+
81+
If you are trying to prevent actions from changing state, **that is not what `filter` is for**. The `filter` option only prevents state changes from becoming part of the history, i.e. the new state being pushed into `state.past`. If you need this functionality, check out [redux-ignore](https://github.com/omnidan/redux-ignore).
82+
83+
On the other hand, here is how to use the helper functions:
84+
85+
```js
86+
undoable(myReducer, {
87+
filter: combineFilters(
88+
// includeAction/excludeAction helpers take an array of action type strings
89+
includeAction(["MY_ACTION", "ANOTHER_ACTION"]),
90+
costumeFilter
91+
)
92+
});
93+
```
94+
95+
When writing a custom filter, return `true` for actions that you want to keep in history.
96+
97+
```js
98+
function onlyEveryThird(action, newState, history) {
99+
// Access the whole history object
100+
let { past, present, future, limit } = history;
101+
102+
return newState.count % 3 === 0; // Only update history every third count
103+
}
104+
```
105+
106+
## What is `_latestUnfiltered`? Can I remove it?
107+
108+
### What is it?
109+
110+
State wrapped by `undoable()` contains the field `_latestUnfiltered` alongside `past`, `present`, etc. This field is used to keep track of state that should be put in the history but cannot yet because the previous action(s) were filtered. It is basically a temporary variable between filtered actions.
111+
112+
```js
113+
// This action is filtered, so present cannot be pushed into past right away
114+
_latestUnfiltered = present;
115+
present = newState;
116+
117+
// With the next unfiltered action...
118+
past = [...past, _latestUnfiltered]; // Now we can add it
119+
```
120+
121+
### Can I remove it?
122+
123+
Short answer, no. It is an integral part of filtering actions from history and cannot be removed from the library. You can ignore it completely, but overriding/removing it may have unwanted consequences.
124+
125+
While there is a tad more overhead handling actions in the reducer, it is necessary with the current setup. In the future, there might be optimization that makes this field less burdensome for users that do not use the filtering functionality.
126+
127+
## Why am I getting `Cannot find module 'redux-undo'`?
128+
129+
If you are using redux-undo in a CommonJS or UMD environment, you need to add `.default` to your imports.
130+
131+
```js
132+
// CJS
133+
var undoable = require("redux-undo").default;
134+
135+
// UMD
136+
var undoable = window.ReduxUndo.default;
137+
```
138+
139+
ES6 imports should work without a hitch.
140+
141+
```js
142+
import undoable from "redux-undo";
143+
```
144+
145+
If this fixed your issue, you might also want to checkout how to [upgrade from 0.6 to 1.0](upgrading-to-1.0.md).

docs/README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
# Table of Contents
22

3-
* [Read Me](/README.md)
4-
* [FAQ](/docs/FAQ.md)
3+
- [Read Me](/README.md)
4+
- [FAQ](/docs/FAQ.md)
5+
- [Upgrading from 0.x to 1.0](/docs/upgrading-to-1.0.md)

docs/upgrading-to-1.0.md

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
# Upgrading redux-undo from 0.x to 1.0
2+
3+
## Imports
4+
5+
CommonJS and UMD bundles now need a `.default` added to your imports.
6+
7+
```js
8+
// CJS
9+
var undoable = require("redux-undo").default;
10+
11+
// UMD
12+
var undoable = window.ReduxUndo.default;
13+
```
14+
15+
ES6 imports should work as expected.
16+
17+
```js
18+
import undoable from "redux-undo";
19+
```
20+
21+
## `distinctState()` filter applied by default
22+
23+
In 1.0 and greater, state is only added to history if it is different than the previous state (checked by object reference equality `===`). The `distinctState()` filter is now deprecated and removed as there is no need for it.
24+
25+
## History API change in versions `< 0.4`
26+
27+
In versions 0.3 and earlier, the history state was stored in the form.
28+
29+
```js
30+
{
31+
currentState: {...currentStateHere...},
32+
history: {
33+
past: [...pastStatesHere...],
34+
present: {...currentStateHere...},
35+
future: [...futureStatesHere...]
36+
}
37+
}
38+
```
39+
40+
In versions `0.4` and greater, the full history is exposed directly.
41+
42+
```js
43+
{
44+
past: [...pastStatesHere...],
45+
present: {...currentStateHere...},
46+
future: [...futureStatesHere...]
47+
}
48+
```
49+
50+
## InitialState
51+
52+
Before `1.0`, you would pass an `initialState` or `initialHistory` as a config option.
53+
54+
```js
55+
undoable(myReducer, {
56+
initialState: {
57+
myState: "initial",
58+
otherField: true
59+
}
60+
// or initialHistory with past, present, and future
61+
});
62+
```
63+
64+
Now, these options are removed in favor of Redux's `preloadedState` parameter.
65+
66+
```js
67+
const rootReducer = combineReducers({
68+
myReducer: undoable(myReducer)
69+
});
70+
71+
const store = createStore(rootReducer, {
72+
myReducer: {
73+
myState: "initial",
74+
otherField: true
75+
}
76+
});
77+
```
78+
79+
When providing initial state, redux-undo will automatically detect whether or not it is a complete history (with `past`, `present`, `future`) or not. If it is not, it will automatically convert it to one.
80+
81+
If you wish to provide an initial history, e.g. you want to prefill `past` to recover a previous session, you **must** provide the three fields for redux-undo to recognize it as a history object.
82+
83+
```js
84+
const store = createStore(rootReducer, {
85+
myReducer: {
86+
past: ["from", "previous", "session"],
87+
present: "now"
88+
// `future` not provided!! Redux-undo will not recognize this as a history
89+
// and will instead set present = {past: [...], present: 'now'}
90+
91+
// To fix, pass `future: []`
92+
}
93+
});
94+
```

0 commit comments

Comments
 (0)