• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

alibaba / hooks / #31

pending completion
#31

push

travis-pro

web-flow
chore: update to jest 29 (#2048)

* chore: update to jest 29

* chore: fix `ts-jest` config is deprecated

895 of 1206 branches covered (74.21%)

Branch coverage included in aggregate %.

2190 of 2576 relevant lines covered (85.02%)

81.45 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/packages/use-url-state/src/index.ts
1
import { useMemoizedFn, useUpdate } from 'ahooks';
×
2
import { parse, stringify } from 'query-string';
×
3
import type { ParseOptions, StringifyOptions } from 'query-string';
4
import { useMemo, useRef } from 'react';
×
5
import type * as React from 'react';
6
import * as tmp from 'react-router';
×
7

8
// ignore waring `"export 'useNavigate' (imported as 'rc') was not found in 'react-router'`
9
const rc = tmp as any;
×
10

11
export interface Options {
12
  navigateMode?: 'push' | 'replace';
13
  parseOptions?: ParseOptions;
14
  stringifyOptions?: StringifyOptions;
15
}
16

17
const baseParseConfig: ParseOptions = {
×
18
  parseNumbers: false,
19
  parseBooleans: false,
20
};
21

22
const baseStringifyConfig: StringifyOptions = {
×
23
  skipNull: false,
24
  skipEmptyString: false,
25
};
26

27
type UrlState = Record<string, any>;
28

29
const useUrlState = <S extends UrlState = UrlState>(
×
30
  initialState?: S | (() => S),
31
  options?: Options,
32
) => {
33
  type State = Partial<{ [key in keyof S]: any }>;
34
  const { navigateMode = 'push', parseOptions, stringifyOptions } = options || {};
×
35

36
  const mergedParseOptions = { ...baseParseConfig, ...parseOptions };
×
37
  const mergedStringifyOptions = { ...baseStringifyConfig, ...stringifyOptions };
×
38

39
  const location = rc.useLocation();
×
40

41
  // react-router v5
42
  const history = rc.useHistory?.();
×
43
  // react-router v6
44
  const navigate = rc.useNavigate?.();
×
45

46
  const update = useUpdate();
×
47

48
  const initialStateRef = useRef(
×
49
    typeof initialState === 'function' ? (initialState as () => S)() : initialState || {},
×
50
  );
51

52
  const queryFromUrl = useMemo(() => {
×
53
    return parse(location.search, mergedParseOptions);
×
54
  }, [location.search]);
55

56
  const targetQuery: State = useMemo(
×
57
    () => ({
×
58
      ...initialStateRef.current,
59
      ...queryFromUrl,
60
    }),
61
    [queryFromUrl],
62
  );
63

64
  const setState = (s: React.SetStateAction<State>) => {
×
65
    const newQuery = typeof s === 'function' ? s(targetQuery) : s;
×
66

67
    // 1. 如果 setState 后,search 没变化,就需要 update 来触发一次更新。比如 demo1 直接点击 clear,就需要 update 来触发更新。
68
    // 2. update 和 history 的更新会合并,不会造成多次更新
69
    update();
×
70
    if (history) {
×
71
      history[navigateMode](
×
72
        {
73
          hash: location.hash,
74
          search: stringify({ ...queryFromUrl, ...newQuery }, mergedStringifyOptions) || '?',
×
75
        },
76
        location.state,
77
      );
78
    }
79
    if (navigate) {
×
80
      navigate(
×
81
        {
82
          hash: location.hash,
83
          search: stringify({ ...queryFromUrl, ...newQuery }, mergedStringifyOptions) || '?',
×
84
        },
85
        {
86
          replace: navigateMode === 'replace',
87
          state: location.state,
88
        },
89
      );
90
    }
91
  };
92

93
  return [targetQuery, useMemoizedFn(setState)] as const;
×
94
};
95

96
export default useUrlState;
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc