Skip to content

Commit

Permalink
Merge f2ab2d2 into cfd0140
Browse files Browse the repository at this point in the history
  • Loading branch information
beizhedenglong committed May 14, 2019
2 parents cfd0140 + f2ab2d2 commit 87467d3
Show file tree
Hide file tree
Showing 7 changed files with 213 additions and 27 deletions.
49 changes: 26 additions & 23 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,30 +12,31 @@ Visit [here](https://github.com/beizhedenglong/react-hooks-lib/blob/master/examp

## Hooks

| Name | Arguments | Returns |
| -------------------------------------------------------- | ----------------------------------- | ------------------------------------------------------------ |
| <h6>Lifecycles</h6> | | |
| [`useDidMount`](#usedidmountf) | f | - |
| [`useWillUnmount`](#usewillunmountf) | f | - |
| [`useDidUpdate`](#usedidupdatef-options) | f, conditions | - |
| <h6>State</h6> | | |
| [`createContextState`](#createContextStateInitial) | initial | { ContextProvider, ContextConsumer, set, useContextState } |
| [`createGlobalState`](#createGlobalStateInitial) | initial | { GlobalProvider, GlobalConsumer, set, useGlobalState } |
| [`useMergeState`](#usemergestateinitial) | initial | { state, set } |
| [`useCounter`](#useCounterInitial) | initial | { count, set, reset, inc, dec } |
| [`useToggle`](#useToggleInitial) | initial | { on, set, reset, toggle } |
| [`useList`](#useListInitial) | initial | { list, set, reset, push, sort, filter } |
| [`useMap`](#useMapInitial) | initial | { values, set, reset, clear, get, has, del } |
| <h6>Network</h6> | | |
| Name | Arguments | Returns |
| -------------------------------------------------------- | ---------------------------------- | ------------------------------------------------------------ |
| <h6>Lifecycles</h6> | | |
| [`useDidMount`](#usedidmountf) | f | - |
| [`useWillUnmount`](#usewillunmountf) | f | - |
| [`useDidUpdate`](#usedidupdatef-options) | f, conditions | - |
| <h6>State</h6> | | |
| [`createContextState`](#createContextStateInitial) | initial | { ContextProvider, ContextConsumer, set, useContextState } |
| [`createGlobalState`](#createGlobalStateInitial) | initial | { GlobalProvider, GlobalConsumer, set, useGlobalState } |
| [`useMergeState`](#usemergestateinitial) | initial | { state, set } |
| [`useUndo`](#useUndoInitial) | initial | { past, present, future, set, undo, redo } |
| [`useCounter`](#useCounterInitial) | initial | { count, set, reset, inc, dec } |
| [`useToggle`](#useToggleInitial) | initial | { on, set, reset, toggle } |
| [`useList`](#useListInitial) | initial | { list, set, reset, push, sort, filter } |
| [`useMap`](#useMapInitial) | initial | { values, set, reset, clear, get, has, del } |
| <h6>Network</h6> | | |
| [`useFetch`](#useFetchInitialUrl-initialOptions-onMount) | initialUrl, initialOptions, config | { loading, data, error, fetch, setUrl, setOptions, setData } |
| [`useOnlineStatus`](#useonlinestatus) | | |
| <h6>Feedback</h6> | | |
| [`useHover`](#useHover) | - | { hovered, bind } |
| [`useActive`](#useActive) | - | { active, bind } |
| [`useFocus`](#useFocus) | - | { focused, bind } |
| [`useTouch`](#useTouch) | - | { touched, bind } |
| <h6>Data Entry</h6> | | |
| [`useField`](#useFieldInitial) | initial | { value, set, reset, bind } |
| [`useOnlineStatus`](#useonlinestatus) | | |
| <h6>Feedback</h6> | | |
| [`useHover`](#useHover) | - | { hovered, bind } |
| [`useActive`](#useActive) | - | { active, bind } |
| [`useFocus`](#useFocus) | - | { focused, bind } |
| [`useTouch`](#useTouch) | - | { touched, bind } |
| <h6>Data Entry</h6> | | |
| [`useField`](#useFieldInitial) | initial | { value, set, reset, bind } |


## API
Expand Down Expand Up @@ -116,6 +117,8 @@ const MergeState = () => {
}
```

### `useUndo(initial)`

### `useCounter(initial)`
```js
import { useCounter } from 'react-hooks-lib'
Expand Down
57 changes: 57 additions & 0 deletions __tests__/useUndo.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { renderHook, act } from 'react-hooks-testing-library'
import { useUndo } from '../src'

test('useUndo', () => {
const { result } = renderHook(() => useUndo(0))
expect(result.current.present).toEqual(0)
expect(result.current.past).toEqual([])
expect(result.current.future).toEqual([])

act(() => result.current.set(prev => prev + 1))
expect(result.current.past).toEqual([0])
expect(result.current.present).toEqual(1)
expect(result.current.future).toEqual([])

act(() => result.current.set(prev => prev + 1))
expect(result.current.past).toEqual([0, 1])
expect(result.current.present).toEqual(2)
expect(result.current.future).toEqual([])

act(() => result.current.undo())
expect(result.current.past).toEqual([0])
expect(result.current.present).toEqual(1)
expect(result.current.future).toEqual([2])

act(() => result.current.undo())
expect(result.current.past).toEqual([])
expect(result.current.present).toEqual(0)
expect(result.current.future).toEqual([1, 2])

act(() => result.current.redo())
expect(result.current.past).toEqual([0])
expect(result.current.present).toEqual(1)
expect(result.current.future).toEqual([2])

act(() => result.current.set(3))
expect(result.current.past).toEqual([0, 1])
expect(result.current.present).toEqual(3)
expect(result.current.future).toEqual([])

act(() => {
result.current.undo()
result.current.undo()
result.current.undo()
})
expect(result.current.past).toEqual([])
expect(result.current.present).toEqual(0)
expect(result.current.future).toEqual([1, 3])

act(() => {
result.current.redo()
result.current.redo()
result.current.redo()
})
expect(result.current.past).toEqual([0, 1])
expect(result.current.present).toEqual(3)
expect(result.current.future).toEqual([])
})
33 changes: 30 additions & 3 deletions example/example.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,34 @@ import {
useToggle, useCounter, useHover, useActive, useFocus,
useList, useMap, useField, useFetch, useTouch, useMergeState,
useOnlineStatus, useDidMount, useWillUnmount, useDidUpdate,
createContextState,
createContextState, useUndo,
} from '../src/index'

const UndoCounter = () => {
const {
past, present, future, set, undo, redo,
} = useUndo(0)
return (
<div>
<h3>useUndo</h3>
{`counter: ${present}`}
<button onClick={() => set(prev => prev + 1)}>+1</button>
<button
onClick={undo}
disabled={past.length === 0}
>
undo
</button>
<button
onClick={redo}
disabled={future.length === 0}
>
redo
</button>
</div>
)
}

const MergeState = () => {
const { state, set } = useMergeState({ name: 'Victor', age: 1 })
return (
Expand Down Expand Up @@ -245,6 +270,8 @@ const ContextState = () => {

ReactDOM.render(
<div>
<UndoCounter />
<br />
<ContextProvider>
<ContextState />
</ContextProvider>
Expand All @@ -270,8 +297,8 @@ ReactDOM.render(
<hr />
<Select />
<hr />
<Fetch />
<PostFetch />
{/* <Fetch />
<PostFetch /> */}
<hr />
<OnlineStatus />
<hr />
Expand Down
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "react-hooks-lib",
"version": "0.0.17",
"version": "0.0.18",
"main": "dist/react-hooks-lib.js",
"umd:main": "dist/react-hooks-lib.umd.js",
"module": "dist/react-hooks-lib.m.js",
Expand Down Expand Up @@ -41,6 +41,8 @@
"parcel-bundler": "^1.10.3",
"react": "^16.8.2",
"react-dom": "^16.8.2",
"react-hooks-testing-library": "^0.5.0",
"react-test-renderer": "^16.8.6",
"react-testing-library": "^5.9.0",
"regenerator-runtime": "^0.13.1"
},
Expand Down
53 changes: 53 additions & 0 deletions src/hooks/useUndo.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import useMergeState from './useMergeState'

const useUndo = (initial) => {
const {
state,
set,
} = useMergeState({
past: [],
present: initial,
future: [],
})
const undo = () => {
set((prevState) => {
const { past, present, future } = prevState
if (past.length === 0) {
return prevState
}
const previous = past[past.length - 1]
return {
past: past.slice(0, past.length - 1),
present: previous,
future: [present, ...future],
}
})
}
const redo = () => {
set((prevState) => {
const { past, present, future } = prevState
if (future.length === 0) {
return prevState
}
const [next, ...restFuture] = future
return {
past: [...past, present],
present: next,
future: restFuture,
}
})
}
const setPresent = updater => set(({ present, past }) => ({
past: [...past, present],
present: typeof updater === 'function' ? updater(present) : updater,
future: [],
}))
return {
...state,
undo,
redo,
set: setPresent,
}
}

export default useUndo
2 changes: 2 additions & 0 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,5 @@ export { default as useDidUpdate } from './hooks/useDidUpdate'
export { default as useWillUnmount } from './hooks/useWillUnmount'

export { default as createGlobalState, createContextState } from './hooks/useGlobalState'

export { default as useUndo } from './hooks/useUndo'
42 changes: 42 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -645,6 +645,13 @@
dependencies:
regenerator-runtime "^0.12.0"

"@babel/runtime@^7.4.2":
version "7.4.4"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.4.4.tgz#dc2e34982eb236803aa27a07fea6857af1b9171d"
integrity sha512-w0+uT71b6Yi7i5SE0co4NioIpSYS6lLiXvCzWzGSKvpK5vdQtCbICHMj+gbAKAOtxiV6HsVh/MBdaF9EQ6faSg==
dependencies:
regenerator-runtime "^0.13.2"

"@babel/template@^7.0.0", "@babel/template@^7.1.0", "@babel/template@^7.1.2", "@babel/template@^7.2.2":
version "7.2.2"
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.2.2.tgz#005b3fdf0ed96e88041330379e0da9a708eb2907"
Expand Down Expand Up @@ -6697,6 +6704,28 @@ react-dom@^16.8.2:
prop-types "^15.6.2"
scheduler "^0.13.2"

react-hooks-testing-library@^0.5.0:
version "0.5.0"
resolved "https://registry.yarnpkg.com/react-hooks-testing-library/-/react-hooks-testing-library-0.5.0.tgz#571af3522f88ea4ac23c634fb4deff84873f2bc2"
integrity sha512-qX4SA28pcCCf1Q23Gtl1VKqQk26pSPTEsdLtfJanDqm4oacT5wadL+e2Xypk/H+AOXN5kdZrWmXkt+hAaiNHgg==
dependencies:
"@babel/runtime" "^7.4.2"

react-is@^16.8.6:
version "16.8.6"
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.8.6.tgz#5bbc1e2d29141c9fbdfed456343fe2bc430a6a16"
integrity sha512-aUk3bHfZ2bRSVFFbbeVS4i+lNPZr3/WM5jT2J5omUVV1zzcs1nAaf3l51ctA5FFvCRbhrH0bdAsRRQddFJZPtA==

react-test-renderer@^16.8.6:
version "16.8.6"
resolved "https://registry.yarnpkg.com/react-test-renderer/-/react-test-renderer-16.8.6.tgz#188d8029b8c39c786f998aa3efd3ffe7642d5ba1"
integrity sha512-H2srzU5IWYT6cZXof6AhUcx/wEyJddQ8l7cLM/F7gDXYyPr4oq+vCIxJYXVGhId1J706sqziAjuOEjyNkfgoEw==
dependencies:
object-assign "^4.1.1"
prop-types "^15.6.2"
react-is "^16.8.6"
scheduler "^0.13.6"

react-testing-library@^5.9.0:
version "5.9.0"
resolved "https://registry.yarnpkg.com/react-testing-library/-/react-testing-library-5.9.0.tgz#e1c8a586d2f2cbd5f0035474ca90258eef1fece6"
Expand Down Expand Up @@ -6843,6 +6872,11 @@ regenerator-runtime@^0.13.1:
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.1.tgz#522ea2aafd9200a00eee143dc14219a35a0f3991"
integrity sha512-5KzMIyPLvfdPmvsdlYsHqITrDfK9k7bmvf97HvHSN4810i254ponbxCQ1NukpRWlu6en2MBWzAlhDExEKISwAA==

regenerator-runtime@^0.13.2:
version "0.13.2"
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.2.tgz#32e59c9a6fb9b1a4aff09b4930ca2d4477343447"
integrity sha512-S/TQAZJO+D3m9xeN1WTI8dLKBBiRgXBlTJvbWjCThHWZj9EvHK70Ff50/tYj2J/fvBY6JtFVwRuazHN2E7M9BA==

regenerator-transform@^0.13.3:
version "0.13.3"
resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.13.3.tgz#264bd9ff38a8ce24b06e0636496b2c856b57bcbb"
Expand Down Expand Up @@ -7301,6 +7335,14 @@ scheduler@^0.13.2:
loose-envify "^1.1.0"
object-assign "^4.1.1"

scheduler@^0.13.6:
version "0.13.6"
resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.13.6.tgz#466a4ec332467b31a91b9bf74e5347072e4cd889"
integrity sha512-IWnObHt413ucAYKsD9J1QShUKkbKLQQHdxRyw73sw4FN26iWr3DY/H34xGPe4nmL1DwXyWmSWmMrA9TfQbE/XQ==
dependencies:
loose-envify "^1.1.0"
object-assign "^4.1.1"

"semver@2 || 3 || 4 || 5", semver@^5.3.0, semver@^5.4.1, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0:
version "5.6.0"
resolved "https://registry.yarnpkg.com/semver/-/semver-5.6.0.tgz#7e74256fbaa49c75aa7c7a205cc22799cac80004"
Expand Down

0 comments on commit 87467d3

Please sign in to comment.