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

chore: merge master to v4 #2544

Merged
merged 19 commits into from
May 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
e55414b
refactor: replace lodash/isEqual with react-fast-compare (#2458)
guoyunhe Feb 29, 2024
256a753
refactor(useRafInterval): optimize useEffect cleanup fn (#2426)
coding-ice Mar 5, 2024
15afaa6
fix(useAntdTable): 修复动态设置 ready 失效的 bug (#2489)
guaijie Mar 13, 2024
866087a
refactor(useLockFn): catch to finally (#2421)
coding-ice Mar 13, 2024
43d3ae8
refactor(createEffectWithTarget): the first parameter is old-deps (#2…
coding-ice Mar 13, 2024
120099c
fix(useCountDown): targetDate resets leftTime (#2346)
joe-leong Mar 13, 2024
dff2795
chore: update version
crazylxr Apr 1, 2024
d9d73a5
fix(type): fixed up some types that are non-standard and errors on `u…
LonelyFellas Apr 2, 2024
1c3d026
feat(useStoage): listen to `storage` event (#2298)
vaakian Apr 21, 2024
c7aea2b
chore(useLatest): add a default state for comparison in useLatest dem…
shfshanyue Apr 21, 2024
265a921
feat(useSelections): support object array (#2485)
liuyib Apr 21, 2024
6d3c3ba
修复 useAntdTable Params 的类型问题 (#2377)
conorzhong Apr 21, 2024
3ba7cb6
fix(useVirtualList): get correct offset when itemHeight is fixed (#2279)
leedawn Apr 21, 2024
4841696
fix(createUseStorageState): invoke setState twice (#2532)
liuyib Apr 25, 2024
e67bbfb
fix: 🐞 every add default value (#2529)
enson0131 Apr 25, 2024
7c53711
feat(useDynamicList): add `batchRemove` method (#2340)
xiaozisong Apr 25, 2024
5f9da3e
feat(useSelections): add clearAll result (#2357)
lich-yoo Apr 25, 2024
6bec34c
test(useSelections): fix test case error (#2536)
liuyib Apr 25, 2024
1dae5f7
Merge branch 'master' into chore_merge_main
liuyib May 6, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/guide/upgrade.en-US.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ The package.json will be:

Now, ahooks in your project is still v4, and ahooks4 is v5:

```tsx
```tsx | pure
import React from 'react';
import { useRequest } from 'ahooks'; // v3
import { useRequest } from 'ahooks4'; // v4
Expand Down
2 changes: 1 addition & 1 deletion docs/guide/upgrade.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ $ bun add ahooks4@npm:ahooks@4

现在,你项目中的 ahooks 还是 v3 版本,ahooks4 是 v4 版本:

```tsx
```tsx | pure
import React from 'react';
import { useRequest } from 'ahooks'; // v3
import { useRequest } from 'ahooks4'; // v4
Expand Down
6 changes: 5 additions & 1 deletion packages/hooks/src/createUseStorageState/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,10 @@ export function createUseStorageState(getStorage: () => Storage | undefined) {

const updateState = (value?: SetState<T>) => {
const currentState = isFunction(value) ? value(state) : value;
setState(currentState);

if (!listenStorageChange) {
setState(currentState);
}

try {
let newValue: string | null;
Expand Down Expand Up @@ -126,5 +129,6 @@ export function createUseStorageState(getStorage: () => Storage | undefined) {

return [state, useMemoizedFn(updateState)] as const;
}

return useStorageState;
}
21 changes: 21 additions & 0 deletions packages/hooks/src/useDynamicList/__tests__/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,15 @@ import useDynamicList from '../index';

describe('useDynamicList', () => {
const setUp = (props: any): any => renderHook(() => useDynamicList(props));
const warnSpy = jest.spyOn(console, 'error').mockImplementation(() => {});

afterEach(() => {
warnSpy.mockReset();
});

afterAll(() => {
warnSpy.mockRestore();
});

it('getKey should work', () => {
const hook = setUp([1, 2, 3]);
Expand Down Expand Up @@ -97,6 +106,18 @@ describe('useDynamicList', () => {
hook.result.current.remove(7);
});
expect(hook.result.current.list.length).toBe(7);

// batch remove
act(() => {
hook.result.current.batchRemove(1);
});
expect(warnSpy).toHaveBeenCalledWith(
'`indexes` parameter of `batchRemove` function expected to be an array, but got "number".',
);
act(() => {
hook.result.current.batchRemove([0, 1, 2]);
});
expect(hook.result.current.list.length).toBe(4);
});

it('same items should have different keys', () => {
Expand Down
29 changes: 22 additions & 7 deletions packages/hooks/src/useDynamicList/demo/demo1.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,13 @@
*/

import React from 'react';
import { Input, Space } from 'antd';
import { Button, Input, Space } from 'antd';
import { MinusCircleOutlined, PlusCircleOutlined } from '@ant-design/icons';
import { useDynamicList } from 'ahooks';

export default () => {
const { list, remove, getKey, insert, replace } = useDynamicList(['David', 'Jack']);
const { list, remove, batchRemove, getKey, insert, replace } = useDynamicList(['David', 'Jack']);
const listIndexes = list.map((item, index) => index);

const Row = (index: number, item: any) => (
<Space key={getKey(index)}>
Expand All @@ -27,11 +28,25 @@ export default () => {
);

return (
<>
<Space style={{ marginBottom: 16 }} direction="vertical">
{list.map((ele, index) => Row(index, ele))}
<Space direction="vertical">
<Space direction="vertical">{list.map((ele, index) => Row(index, ele))}</Space>
<Space>
<Button
danger
disabled={list.length <= 1}
onClick={() => batchRemove(listIndexes.filter((index) => index % 2 === 0))}
>
Remove odd items
</Button>
<Button
danger
disabled={list.length <= 1}
onClick={() => batchRemove(listIndexes.filter((index) => index % 2 !== 0))}
>
Remove even items
</Button>
</Space>
<p>{JSON.stringify(list)}</p>
</>
<div>{JSON.stringify([list])}</div>
</Space>
);
};
33 changes: 33 additions & 0 deletions packages/hooks/src/useDynamicList/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { useCallback, useRef, useState } from 'react';
import isDev from '../utils/isDev';

const useDynamicList = <T>(initialList: T[] = []) => {
const counterRef = useRef(-1);
Expand Down Expand Up @@ -77,6 +78,37 @@ const useDynamicList = <T>(initialList: T[] = []) => {
});
}, []);

const batchRemove = useCallback((indexes: number[]) => {
if (!Array.isArray(indexes)) {
if (isDev) {
console.error(
`\`indexes\` parameter of \`batchRemove\` function expected to be an array, but got "${typeof indexes}".`,
);
}
return;
}
if (!indexes.length) {
return;
}

setList((prevList) => {
const newKeyList: number[] = [];
const newList = prevList.filter((item, index) => {
const shouldKeep = !indexes.includes(index);

if (shouldKeep) {
newKeyList.push(getKey(index));
}

return shouldKeep;
});

keyList.current = newKeyList;

return newList;
});
}, []);

const move = useCallback((oldIndex: number, newIndex: number) => {
if (oldIndex === newIndex) {
return;
Expand Down Expand Up @@ -150,6 +182,7 @@ const useDynamicList = <T>(initialList: T[] = []) => {
merge,
replace,
remove,
batchRemove,
getKey,
getIndex,
move,
Expand Down
4 changes: 2 additions & 2 deletions packages/hooks/src/useFullscreen/demo/demo4.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
/**
* title: Coexist with other full screen operations
* desc: The element's full screen may be modified by other scripts, don't worry, ahooks can work with them.
* description: The element's full screen may be modified by other scripts, don't worry, ahooks can work with them.
*
* title.zh-CN: 与其它全屏操作共存
* desc.zh-CN: 元素的全屏情况可能被其它脚本修改,不用担心,ahooks 可以与它们共存。
* description.zh-CN: 元素的全屏情况可能被其它脚本修改,不用担心,ahooks 可以与它们共存。
*/

import React, { useRef } from 'react';
Expand Down
4 changes: 2 additions & 2 deletions packages/hooks/src/useKeyPress/demo/demo8.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
/**
* title: Get the trigger key
* desc: Multiple shortcuts are registered by a hook, each corresponding to a different logic.
* description: Multiple shortcuts are registered by a hook, each corresponding to a different logic.
*
* title.zh-CN: 获取触发的按键
* desc.zh-CN: 单个 hook 注册多个快捷键,每个快捷键对应不同逻辑。
* description.zh-CN: 单个 hook 注册多个快捷键,每个快捷键对应不同逻辑。
*/

import React, { useState } from 'react';
Expand Down
22 changes: 9 additions & 13 deletions packages/hooks/src/useLocalStorageState/demo/demo4.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,21 @@
/**
* title: Sync state with localStorage
* desc: When the stored value changes, all `useLocalStorageState` with the same `key` will synchronize their states, including different tabs of the same browser (try to open two tabs of this page, clicking a button on one page will automatically update the "count" on the other page).
* description: When the stored value changes, all `useLocalStorageState` with the same `key` will synchronize their states, including different tabs of the same browser (try to open two tabs of this page, clicking a button on one page will automatically update the "count" on the other page).
*
* title.zh-CN: 将 state 与 localStorage 保持同步
* desc.zh-CN: 存储值变化时,所有 `key` 相同的 `useLocalStorageState` 会同步状态,包括同一浏览器不同 tab 之间(尝试打开两个此页面,点击其中一个页面的按钮,另一个页面的 count 会自动更新)
* description.zh-CN: 存储值变化时,所有 `key` 相同的 `useLocalStorageState` 会同步状态,包括同一浏览器不同 tab 之间(尝试打开两个此页面,点击其中一个页面的按钮,另一个页面的 count 会自动更新)
*/

import React from 'react';
import { Button, Space } from 'antd';
import { useLocalStorageState } from 'ahooks';

export default function () {
return (
<>
<Space direction="vertical">
<Counter />
<Counter />
</>
</Space>
);
}

Expand All @@ -24,15 +25,10 @@ function Counter() {
listenStorageChange: true,
});

const add = () => setCount(count! + 1);
const clear = () => setCount();

return (
<div style={{ marginBottom: '8px' }}>
<button style={{ marginRight: '8px' }} onClick={add}>
count: {count}
</button>
<button onClick={clear}>Clear</button>
</div>
<Space>
<Button onClick={() => setCount(count! + 1)}>count: {count}</Button>
<Button onClick={() => setCount()}>Clear</Button>
</Space>
);
}
5 changes: 1 addition & 4 deletions packages/hooks/src/useLocalStorageState/index.en-US.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,7 @@ A Hook that store state into localStorage.
<code src="./demo/demo1.tsx"></code>
<code src="./demo/demo2.tsx"></code>
<code src="./demo/demo3.tsx"></code>

### Sync state with localStorage

<code src="./demo/demo4.tsx" />
<code src="./demo/demo4.tsx"></code>

## API

Expand Down
5 changes: 1 addition & 4 deletions packages/hooks/src/useLocalStorageState/index.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,7 @@ demo:
<code src="./demo/demo1.tsx"></code>
<code src="./demo/demo2.tsx"></code>
<code src="./demo/demo3.tsx"></code>

### 将 state 与 localStorage 保持同步

<code src="./demo/demo4.tsx" />
<code src="./demo/demo4.tsx"></code>

## API

Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
/**
* title: Repeat last request
* desc: When the dependency array changes, use the previous parameters to make the request again.
* description: When the dependency array changes, use the previous parameters to make the request again.
*
* title.zh-CN: 重复上一次请求
* desc.zh-CN: 依赖数组变化时,使用上一次的参数重新发起请求。
* description.zh-CN: 依赖数组变化时,使用上一次的参数重新发起请求。
*/

import React, { useState } from 'react';
Expand Down
42 changes: 42 additions & 0 deletions packages/hooks/src/useSelections/__tests__/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { act, renderHook } from '@testing-library/react';
import { useState } from 'react';
import useSelections from '../index';
import type { Options } from '../index';

Expand Down Expand Up @@ -193,4 +194,45 @@ describe('useSelections', () => {
expect(result.current.selected).toEqual(_selected);
expect(result.current.isSelected(_selectedItem)).toBe(true);
});

it('clearAll should work correct', async () => {
const runCase = (data, newData, remainData) => {
const { result } = renderHook(() => {
const [list, setList] = useState(data);
const hook = useSelections(list, {
itemKey: 'id',
});

return { setList, hook };
});
const { setSelected, unSelectAll, clearAll } = result.current.hook;

act(() => {
setSelected(data);
});
expect(result.current.hook.selected).toEqual(data);
expect(result.current.hook.allSelected).toBe(true);

act(() => {
result.current.setList(newData);
});
expect(result.current.hook.allSelected).toBe(false);

act(() => {
unSelectAll();
});
expect(result.current.hook.selected).toEqual(remainData);

act(() => {
clearAll();
});
expect(result.current.hook.selected).toEqual([]);
expect(result.current.hook.allSelected).toEqual(false);
expect(result.current.hook.noneSelected).toBe(true);
expect(result.current.hook.partiallySelected).toBe(false);
};

runCase(_data, [3, 4, 5], [1, 2]);
runCase(_dataObj, [{ id: 3 }, { id: 4 }, { id: 5 }], [{ id: 1 }, { id: 2 }]);
});
});
4 changes: 2 additions & 2 deletions packages/hooks/src/useSelections/demo/demo2.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
/**
* title: Object array
* desc: When array items are object, you need to specify the field name for the unique key.
* description: When array items are object, you need to specify the field name for the unique key.
*
* title.zh-CN: 对象数组
* desc.zh-CN: 数组项是对象时,需要指定唯一 key 的字段名称。
* description.zh-CN: 数组项是对象时,需要指定唯一 key 的字段名称。
*/

import { Checkbox, Col, Row } from 'antd';
Expand Down
4 changes: 2 additions & 2 deletions packages/hooks/src/useSelections/demo/demo3.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
/**
* title: Pagination
* desc: Load data with pagination and enable cross-page selection.
* description: Load data with pagination and enable cross-page selection.
*
* title.zh-CN: 分页多选
* desc.zh-CN: 分页加载数据,并跨页选择。
* description.zh-CN: 分页加载数据,并跨页选择。
*/

import { Checkbox, Divider, Pagination, Spin } from 'antd';
Expand Down