Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/feature/useSearchParams'
Browse files Browse the repository at this point in the history
  • Loading branch information
tangzx committed Oct 13, 2023
2 parents 5a12c4c + 8de77be commit a5a901c
Show file tree
Hide file tree
Showing 15 changed files with 426 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
module.exports = {
extends: require.resolve('@umijs/lint/dist/config/eslint'),
rules: {
'no-param-reassign': 'off',
},
};
38 changes: 38 additions & 0 deletions docs/hooks/useHistory/index.zh-CN.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
---
description: useHistory
group: State
toc: content
---

# useHistory

获取 history 信息

## 代码演示

<code src="let-hooks/useHistory/demos/base.tsx" title="基本用法"></code>

## 用法

```ts
const { location, listen, replace, push, go } = useHistory();
```

## 返回值

| 属性名 | 类型 | 描述 |
| -------- | ------------------------------- | ---------------------------- |
| location | `Location` | [Location](#location) 数据 |
| listen | `(fn: Listener): () => void` | history 改变的回调 |
| replace | `(to: To, state?: any) => void` | 修改路径(替换当前历史记录) |
| push | `(to: To, state?: any) => void` | 修改路径 |
| go | `(delta: number) => void` | 跳转到距离当前的第几个页面 |

### location

| 属性名 | 类型 | 描述 |
| -------- | -------- | ------------ |
| pathname | `string` | pathname |
| hash | `string` | pahashthname |
| search | `string` | search |
| state | `any` | state |
33 changes: 33 additions & 0 deletions docs/hooks/useLocation/index.zh-CN.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
---
description: useLocation
group: State
toc: content
---

# useLocation

获取 location 信息

## 代码演示

<code src="let-hooks/useLocation/demos/base.tsx" title="基本用法"></code>

## 用法

```ts
const {
pathname,
hash,
search,
state,
} = useLocation();
```

## 返回值

| 属性名 | 类型 | 描述 |
| -------- | -------- | ------------ |
| pathname | `string` | pathname |
| hash | `string` | pahashthname |
| search | `string` | search |
| state | `any` | state |
26 changes: 26 additions & 0 deletions docs/hooks/useSearchParams/index.zh-CN.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
---
description: useSearchParams
group: Effect
toc: content
---

# useSearchParams

获取当前页面 search 数据的 hook

## 代码演示

<code src="let-hooks/useSearchParams/demos/base.tsx"></code>

## API

```ts
const [searchParams, setSearchParams] = useSearchParams();
```

## 返回值

| 返回值 | 类型 | 描述 |
| --------------- | -------------------- | ---------------- |
| searchParams | `URLSearchParams` | search 数据 |
| setSearchParams | `SetURLSearchParams` | 设置 search 数据 |
2 changes: 2 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@ export { default as useEventAway } from './useEventAway';
export { default as useFavicon } from './useFavicon';
export { default as useHash } from './useHash';
export { default as useHidden } from './useHidden';
export { default as useHistory } from './useHistory';
export { default as useIntersection } from './useIntersection';
export { default as useInterval } from './useInterval';
export { default as useLocation } from './useLocation';
export { default as useLRU } from './useLRU';
export { default as useMap } from './useMap';
export { default as useMemoizedFn } from './useMemoizedFn';
Expand Down
17 changes: 17 additions & 0 deletions src/useHistory/__tests__/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { renderHook } from '@testing-library/react';
import useHistory from '..';

describe('Test useHistory', () => {
it('should have correct structure', () => {
const { result } = renderHook(() => useHistory());

expect(result.current).toStrictEqual({
location: expect.any(Object),
listen: expect.any(Function),
replace: expect.any(Function),
push: expect.any(Function),
createHref: expect.any(Function),
go: expect.any(Function),
});
});
});
11 changes: 11 additions & 0 deletions src/useHistory/demos/base.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import useHistory from '..';

export default () => {
const history = useHistory();

return (
<div>
<pre>{JSON.stringify(history, null, 2)}</pre>
</div>
);
};
15 changes: 15 additions & 0 deletions src/useHistory/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { createHistory, History } from '@/utils/history';
import { useMemo } from 'react';

let history: History;

const useHistory = () => {
return useMemo(() => {
if (history) {
return history;
}
return (history = Object.freeze(createHistory()));
}, []);
};

export default useHistory;
14 changes: 14 additions & 0 deletions src/useLocation/__tests__/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { renderHook } from '@testing-library/react';
import useLocation from '..';

describe('test useLocation', () => {
it('should return location data', () => {
const { result } = renderHook(() => useLocation());
expect(result.current).toStrictEqual({
pathname: expect.any(String),
hash: expect.any(String),
search: expect.any(String),
state: undefined,
});
});
});
11 changes: 11 additions & 0 deletions src/useLocation/demos/base.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import useLocation from '..';

export default () => {
const location = useLocation();

return (
<div>
<pre>{JSON.stringify(location, null, 2)}</pre>
</div>
);
};
19 changes: 19 additions & 0 deletions src/useLocation/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import useHistory from '@/useHistory';
import { useEffect, useState } from 'react';

const useLocation = () => {
const history = useHistory();
const [location, setLocation] = useState(() => ({ ...history.location }));
useEffect(() => {
const cancel = history.listen(({ location }) => {
setLocation(location);
});
return () => {
cancel();
};
}, []);

return location;
};

export default useLocation;
22 changes: 22 additions & 0 deletions src/useSearchParams/__tests__/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { renderHook } from '@testing-library/react';
import { act } from 'react-dom/test-utils';
import useSearchParams from '..';

describe('Test useSearchParams', () => {
it('should change the location search', () => {
const { result } = renderHook(() => useSearchParams());
act(() => {
result.current[1]('name=jack');
});
expect(result.current[0].get('name')).toBe('jack');

act(() => {
result.current[1]((searchParams) => {
searchParams.set('age', '23');
return searchParams;
});
});
expect(result.current[0].get('name')).toBe('jack');
expect(result.current[0].get('age')).toBe('23');
});
});
29 changes: 29 additions & 0 deletions src/useSearchParams/demos/base.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { useEffect } from 'react';
import useSearchParams from '..';

export default () => {
const [searchParams, setSearchParams] = useSearchParams();

const update = () => {
setSearchParams({
time: Date.now(),
random: Math.random(),
});
};

useEffect(update, []);

const map = searchParams.entries().reduce((prev, [key, value]) => {
prev[key] = value;
return prev;
}, {});

return (
<div>
<pre>{JSON.stringify(map, null, 2)}</pre>
<button type="button" onClick={update}>
刷新
</button>
</div>
);
};
44 changes: 44 additions & 0 deletions src/useSearchParams/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import useHistory from '@/useHistory';
import useLocation from '@/useLocation';
import isFunction from '@/utils/isFunction';
import { useCallback, useMemo } from 'react';

export type URLSearchParamsInit =
| string[][]
| Record<string, string>
| string
| URLSearchParams;

export type SetURLSearchParams = (
next: URLSearchParamsInit | ((prev: URLSearchParams) => URLSearchParams),
) => void;

const createSearchParams = (init: URLSearchParamsInit): URLSearchParams =>
new URLSearchParams(init);

const useSearchParams = (): [URLSearchParams, SetURLSearchParams] => {
const history = useHistory();
const location = useLocation();

const searchParams = useMemo(
() => createSearchParams(location.search),
[location.search],
);

const setSearchParams = useCallback<SetURLSearchParams>(
(next) => {
const nextSearchParams = createSearchParams(
isFunction(next) ? next(searchParams) : next,
);

history.replace({
search: nextSearchParams.toString(),
});
},
[searchParams],
);

return [searchParams, setSearchParams];
};

export default useSearchParams;
Loading

0 comments on commit a5a901c

Please sign in to comment.