-
Notifications
You must be signed in to change notification settings - Fork 18
/
Copy pathuseCookies.tsx
66 lines (55 loc) · 1.72 KB
/
useCookies.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
import { useContext, useLayoutEffect, useState, useRef, useMemo } from 'react';
import { Cookie, CookieSetOptions } from 'universal-cookie';
import CookiesContext from './CookiesContext';
import { isInBrowser } from './utils';
export default function useCookies<T extends string, U = { [K in T]?: any }>(
dependencies?: T[],
): [
U,
(name: T, value: Cookie, options?: CookieSetOptions) => void,
(name: T, options?: CookieSetOptions) => void,
() => void,
] {
const cookies = useContext(CookiesContext);
if (!cookies) {
throw new Error('Missing <CookiesProvider>');
}
const [allCookies, setCookies] = useState(() =>
cookies.getAll({ doNotUpdate: true }),
);
if (isInBrowser()) {
useLayoutEffect(() => {
function onChange() {
const newCookies = cookies.getAll({
doNotUpdate: true,
});
if (shouldUpdate(dependencies || null, newCookies, allCookies)) {
setCookies(newCookies);
}
}
cookies.addChangeListener(onChange);
return () => {
cookies.removeChangeListener(onChange);
};
}, [cookies, allCookies]);
}
const setCookie = useMemo(() => cookies.set.bind(cookies), [cookies]);
const removeCookie = useMemo(() => cookies.remove.bind(cookies), [cookies]);
const updateCookies = useMemo(() => cookies.update.bind(cookies), [cookies]);
return [allCookies, setCookie, removeCookie, updateCookies];
}
function shouldUpdate<U = { [K: string]: any }>(
dependencies: Array<keyof U> | null,
newCookies: U,
oldCookies: U,
) {
if (!dependencies) {
return true;
}
for (let dependency of dependencies) {
if (newCookies[dependency] !== oldCookies[dependency]) {
return true;
}
}
return false;
}