Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(useHistoryTravel): add manual update option #2278

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 49 additions & 0 deletions packages/hooks/src/useHistoryTravel/__tests__/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -242,4 +242,53 @@ describe('useHistoryTravel', () => {
expect(hook.result.current.backLength).toBe(0);
expect(hook.result.current.value).toBe(90);
});

it('should work with manual', async () => {
const hook = renderHook(() => useHistoryTravel(0, { manual: true }));

act(() => {
hook.result.current.setValue(1);
});
// <0>
// 1
expect(hook.result.current.forwardLength).toBe(0);
expect(hook.result.current.backLength).toBe(0);
expect(hook.result.current.value).toBe(1);

act(() => {
hook.result.current.commit();
});
// 0 <1>
// 1
expect(hook.result.current.forwardLength).toBe(0);
expect(hook.result.current.backLength).toBe(1);
expect(hook.result.current.value).toBe(1);

act(() => {
hook.result.current.commit(2);
});
// 0 1 <2>
// 2
expect(hook.result.current.forwardLength).toBe(0);
expect(hook.result.current.backLength).toBe(2);
expect(hook.result.current.value).toBe(2);

act(() => {
hook.result.current.back();
});
// 0 <1> 2
// 1
expect(hook.result.current.forwardLength).toBe(1);
expect(hook.result.current.backLength).toBe(1);
expect(hook.result.current.value).toBe(1);

act(() => {
hook.result.current.forward();
});
// 0 1 <2>
// 2
expect(hook.result.current.forwardLength).toBe(0);
expect(hook.result.current.backLength).toBe(2);
expect(hook.result.current.value).toBe(2);
});
});
52 changes: 52 additions & 0 deletions packages/hooks/src/useHistoryTravel/demo/demo4.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/**
* title: Manually record history operations
* desc: Only when you click commit, the current data will be recorded.
*
* title.zh-CN: 手动记录历史操作
* desc.zh-CN: 只有点击 commit 后,才会记录当前的数据。
*/

import { useHistoryTravel } from 'ahooks';
import React from 'react';

export default () => {
const { value, setValue, commit, backLength, forwardLength, back, forward } =
useHistoryTravel<number>(0, {
manual: true,
});

const increment = () => {
setValue(value ?? 0 + 1);
};
const decrement = () => {
setValue(value ?? 0 - 1);
};

return (
<div>
<div>Count: {value}</div>
<div style={{ display: 'flex' }}>
<div>
<button onClick={increment} style={{ margin: '0 8px' }}>
+
</button>
<button onClick={decrement} style={{ margin: '0 8px' }}>
-
</button>
</div>
<div>{'/'}</div>
<div>
<button onClick={() => commit()} style={{ margin: '0 8px' }}>
commit
</button>
<button disabled={backLength <= 0} onClick={back} style={{ margin: '0 8px' }}>
back
</button>
<button disabled={forwardLength <= 0} onClick={forward}>
forward
</button>
</div>
</div>
</div>
);
};
35 changes: 31 additions & 4 deletions packages/hooks/src/useHistoryTravel/index.en-US.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,19 +35,46 @@ const {
} = useHistoryTravel<T>(initialValue?: T, maxLength: number = 0 );
```

```typescript
const {
value,
setValue,
commit,
backLength,
forwardLength,
go,
back,
forward
} = useHistoryTravel<T>(
initialValue?: T,
options?: {
maxLength?: number;
manual?: boolean;
});
```

### Params

| Property | Description | Type | Default |
| ------------ | ------------------------------------------------------------------------------------------------------------------------- | -------- | ----------- |
| initialValue | Optional initial value | `T` | - |
| maxLength | Optional limit the maximum length of history records. If the maximum length is exceeded, the first record will be deleted | `number` | 0 unlimited |
| Property | Description | Type | Default |
| ------------ | ------------------------------------------------------------------------------------------------------------------------- | --------- | ----------- |
| initialValue | Optional initial value | `T` | - |
| maxLength | Optional limit the maximum length of history records. If the maximum length is exceeded, the first record will be deleted | `number` | 0 unlimited |
| options | Options | `Options` | - |

### Options

| Property | Description | Type | Default |
| --------- | ------------------------------------------------------------------------------------------------------------------------- | --------- | ----------- |
| maxLength | Optional limit the maximum length of history records. If the maximum length is exceeded, the first record will be deleted | `number` | 0 unlimited |
| manual | Optional Whether to manually submit the record through `commit` | `boolean` | false |

### Result

| Property | Description | Type |
| ------------- | --------------------------------------------------------------------------------- | ------------------------------- |
| value | Current value | `T` |
| setValue | Set value | `(value: T) => void` |
| commit | Manually submit records | `(value: T) => void` |
| backLength | The length of backward history | `number` |
| forwardLength | The length of forward history | `number` |
| go | Move between the history, move backward on step < 0,and move forward on step > 0 | `(step: number) => void` |
Expand Down
43 changes: 39 additions & 4 deletions packages/hooks/src/useHistoryTravel/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,25 @@ const split = <T>(step: number, targetArr: T[]) => {
};
};

export default function useHistoryTravel<T>(initialValue?: T, maxLength: number = 0) {
export default function useHistoryTravel<T>(
initialValue?: T,
options?:
| {
maxLength?: number;
manual?: boolean;
}
| number,
) {
let maxLength = 0;
let manual = false;

if (typeof options === 'number') {
maxLength = options;
Debbl marked this conversation as resolved.
Show resolved Hide resolved
} else if (typeof options === 'object') {
maxLength = options?.maxLength || maxLength;
manual = options?.manual || manual;
Debbl marked this conversation as resolved.
Show resolved Hide resolved
}

const [history, setHistory] = useState<IData<T | undefined>>({
present: initialValue,
past: [],
Expand All @@ -53,7 +71,7 @@ export default function useHistoryTravel<T>(initialValue?: T, maxLength: number
});
};

const updateValue = (val: T) => {
const updateValue = useMemoizedFn((val: T) => {
const _past = [...past, present];
const maxLengthNum = isNumber(maxLength) ? maxLength : Number(maxLength);
// maximum number of records exceeded
Expand All @@ -67,7 +85,23 @@ export default function useHistoryTravel<T>(initialValue?: T, maxLength: number
future: [],
past: _past,
});
};
});

const updateValueWithoutRecord = useMemoizedFn((val?: T) => {
setHistory({
present: val,
future: future,
past: past,
});
});

const commit = useMemoizedFn((val?: T) => {
if (val) {
updateValue(val);
return;
}
return present && updateValue(present);
});

const _forward = (step: number = 1) => {
if (future.length === 0) {
Expand Down Expand Up @@ -109,7 +143,8 @@ export default function useHistoryTravel<T>(initialValue?: T, maxLength: number
value: present,
backLength: past.length,
forwardLength: future.length,
setValue: useMemoizedFn(updateValue),
setValue: manual ? updateValueWithoutRecord : updateValue,
commit,
go: useMemoizedFn(go),
back: useMemoizedFn(() => {
go(-1);
Expand Down
35 changes: 31 additions & 4 deletions packages/hooks/src/useHistoryTravel/index.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,19 +35,46 @@ const {
} = useHistoryTravel<T>(initialValue?: T, maxLength: number = 0);
```

```typescript
const {
value,
setValue,
commit,
backLength,
forwardLength,
go,
back,
forward
} = useHistoryTravel<T>(
initialValue?: T,
options?: {
maxLength?: number;
manual?: boolean;
});
```

### Params

| 参数 | 说明 | 类型 | 默认值 |
| ------------ | --------------------------------------------------------- | -------- | -------- |
| initialValue | 可选,初始值 | `any` | - |
| maxLength | 可选,限制历史记录最大长度,超过最大长度后将删除第一个记录 | `number` | 0 不限制 |
| 参数 | 说明 | 类型 | 默认值 |
| ------------ | --------------------------------------------------------- | --------- | -------- |
| initialValue | 可选,初始值 | `any` | - |
| maxLength | 可选,限制历史记录最大长度,超过最大长度后将删除第一个记录 | `number` | 0 不限制 |
| options | 可选,配置项 | `Options` | - |

### Options

| 参数 | 说明 | 类型 | 默认值 |
| --------- | --------------------------------------------------------- | --------- | -------- |
| maxLength | 可选,限制历史记录最大长度,超过最大长度后将删除第一个记录 | `number` | 0 不限制 |
| manual | 可选,是否通过 commit 手动提交记录 | `boolean` | false |

### Result

| 参数 | 说明 | 类型 |
| ------------- | --------------------------------------------- | ------------------------------- |
| value | 当前值 | `T` |
| setValue | 设置 value | `(value: T) => void` |
| commit | 手动提交记录 | `(value: T) => void` |
| backLength | 可回退历史长度 | `number` |
| forwardLength | 可前进历史长度 | `number` |
| go | 前进步数, step < 0 为后退, step > 0 时为前进 | `(step: number) => void` |
Expand Down