Skip to content

Commit b22f32f

Browse files
committed
feat: 🎸 add useSearchParam() hook
1 parent 1646ecf commit b22f32f

File tree

3 files changed

+57
-0
lines changed

3 files changed

+57
-0
lines changed
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import { storiesOf } from '@storybook/react';
2+
import * as React from 'react';
3+
import { useSearchParam } from '..';
4+
import ShowDocs from './util/ShowDocs';
5+
6+
const Demo = () => {
7+
const foo = useSearchParam('foo');
8+
9+
return (
10+
<div>
11+
<div>foo: {foo || '🤷‍♂️'}</div>
12+
<div>
13+
<button onClick={() => history.pushState({}, '', location.pathname + '?foo=bar')}>foo: bar</button>
14+
</div>
15+
<div>
16+
<button onClick={() => history.pushState({}, '', location.pathname + '?foo=baz')}>foo: baz</button>
17+
</div>
18+
<div>
19+
<button onClick={() => history.pushState({}, '', location.pathname)}>delete</button>
20+
</div>
21+
</div>
22+
);
23+
};
24+
25+
storiesOf('Sensors|useSearchParam', module)
26+
// .add('Docs', () => <ShowDocs md={require('../../docs/useQueryParam.md')} />)
27+
.add('Demo', () => <Demo />);

src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ export { default as useRafLoop } from './useRafLoop';
6363
* @deprecated This hook is obsolete, use `useMountedState` instead
6464
*/
6565
export { default as useRefMounted } from './useRefMounted';
66+
export { default as useSearchParam } from './useSearchParam';
6667
export { default as useScroll } from './useScroll';
6768
export { default as useScrolling } from './useScrolling';
6869
export { default as useSessionStorage } from './useSessionStorage';

src/useSearchParam.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { useState, useEffect } from 'react';
2+
3+
const getValue = (search: string, param: string) => new URLSearchParams(search).get(param);
4+
5+
export type UseQueryParam = (param: string) => string | null;
6+
7+
const useSearchParam: UseQueryParam = param => {
8+
const [value, setValue] = useState<string | null>(() => getValue(location.search, param));
9+
10+
useEffect(() => {
11+
const onChange = () => {
12+
setValue(getValue(location.search, param));
13+
};
14+
15+
window.addEventListener('popstate', onChange);
16+
window.addEventListener('pushstate', onChange);
17+
window.addEventListener('replacestate', onChange);
18+
19+
return () => {
20+
window.removeEventListener('popstate', onChange);
21+
window.removeEventListener('pushstate', onChange);
22+
window.removeEventListener('replacestate', onChange);
23+
};
24+
}, []);
25+
26+
return value;
27+
};
28+
29+
export default useSearchParam;

0 commit comments

Comments
 (0)