mirror of
https://github.com/streamich/react-use.git
synced 2026-01-18 14:06:52 +00:00
feat: add useCookie hook
This commit is contained in:
commit
4e5c90f021
39
docs/useCookie.md
Normal file
39
docs/useCookie.md
Normal file
@ -0,0 +1,39 @@
|
||||
# `useCookie`
|
||||
|
||||
React hook that returns the current value of a `cookie`, a callback to update the `cookie`
|
||||
and a callback to delete the `cookie.`
|
||||
|
||||
## Usage
|
||||
|
||||
```jsx
|
||||
import { useCookie } from "react-use";
|
||||
|
||||
const Demo = () => {
|
||||
const [value, updateCookie, deleteCookie] = useCookie("my-cookie");
|
||||
const [counter, setCounter] = useState(1);
|
||||
|
||||
useEffect(() => {
|
||||
deleteCookie();
|
||||
}, []);
|
||||
|
||||
const updateCookieHandler = () => {
|
||||
updateCookie(`my-awesome-cookie-${counter}`);
|
||||
setCounter(c => c + 1);
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<p>Value: {value}</p>
|
||||
<button onClick={updateCookieHandler}>Update Cookie</button>
|
||||
<br />
|
||||
<button onClick={deleteCookie}>Delete Cookie</button>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
## Reference
|
||||
|
||||
```ts
|
||||
const [value, updateCookie, deleteCookie] = useCookie(cookieName: string);
|
||||
```
|
||||
@ -49,6 +49,7 @@
|
||||
"@xobotyi/scrollbar-width": "1.5.0",
|
||||
"copy-to-clipboard": "^3.2.0",
|
||||
"fast-shallow-equal": "^1.0.0",
|
||||
"js-cookie": "^2.2.1",
|
||||
"nano-css": "^5.2.1",
|
||||
"react-fast-compare": "^2.0.4",
|
||||
"resize-observer-polyfill": "^1.5.1",
|
||||
@ -79,6 +80,7 @@
|
||||
"@storybook/react": "5.3.1",
|
||||
"@testing-library/react-hooks": "3.2.1",
|
||||
"@types/jest": "24.0.25",
|
||||
"@types/js-cookie": "^2.2.4",
|
||||
"@types/react": "16.9.11",
|
||||
"babel-core": "6.26.3",
|
||||
"babel-loader": "8.0.6",
|
||||
|
||||
@ -8,6 +8,7 @@ export { default as useBattery } from './useBattery';
|
||||
export { default as useBeforeUnload } from './useBeforeUnload';
|
||||
export { default as useBoolean } from './useBoolean';
|
||||
export { default as useClickAway } from './useClickAway';
|
||||
export { default as useCookie } from './useCookie';
|
||||
export { default as useCopyToClipboard } from './useCopyToClipboard';
|
||||
export { default as useCounter } from './useCounter';
|
||||
export { default as useCss } from './useCss';
|
||||
|
||||
25
src/useCookie.ts
Normal file
25
src/useCookie.ts
Normal file
@ -0,0 +1,25 @@
|
||||
import { useState, useCallback } from 'react';
|
||||
import Cookies from 'js-cookie';
|
||||
|
||||
const useCookie = (
|
||||
cookieName: string
|
||||
): [string | null, (newValue: string, options?: Cookies.CookieAttributes) => void, () => void] => {
|
||||
const [value, setValue] = useState<string | null>(() => Cookies.get(cookieName) || null);
|
||||
|
||||
const updateCookie = useCallback(
|
||||
(newValue: string, options?: Cookies.CookieAttributes) => {
|
||||
Cookies.set(cookieName, newValue, options);
|
||||
setValue(newValue);
|
||||
},
|
||||
[cookieName]
|
||||
);
|
||||
|
||||
const deleteCookie = useCallback(() => {
|
||||
Cookies.remove(cookieName);
|
||||
setValue(null);
|
||||
}, [cookieName]);
|
||||
|
||||
return [value, updateCookie, deleteCookie];
|
||||
};
|
||||
|
||||
export default useCookie;
|
||||
31
stories/useCookie.story.tsx
Normal file
31
stories/useCookie.story.tsx
Normal file
@ -0,0 +1,31 @@
|
||||
import { storiesOf } from "@storybook/react";
|
||||
import React, { useState, useEffect } from "react";
|
||||
import { useCookie } from "../src";
|
||||
import ShowDocs from "./util/ShowDocs";
|
||||
|
||||
const Demo = () => {
|
||||
const [value, updateCookie, deleteCookie] = useCookie("my-cookie");
|
||||
const [counter, setCounter] = useState(1);
|
||||
|
||||
useEffect(() => {
|
||||
deleteCookie();
|
||||
}, []);
|
||||
|
||||
const updateCookieHandler = () => {
|
||||
updateCookie(`my-awesome-cookie-${counter}`);
|
||||
setCounter(c => c + 1);
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<p>Value: {value}</p>
|
||||
<button onClick={updateCookieHandler}>Update Cookie</button>
|
||||
<br />
|
||||
<button onClick={deleteCookie}>Delete Cookie</button>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
storiesOf("Side effects|useCookie", module)
|
||||
.add("Docs", () => <ShowDocs md={require("../docs/useCookie.md")} />)
|
||||
.add("Demo", () => <Demo />);
|
||||
68
tests/useCookie.test.tsx
Normal file
68
tests/useCookie.test.tsx
Normal file
@ -0,0 +1,68 @@
|
||||
import { renderHook, act } from '@testing-library/react-hooks';
|
||||
import Cookies from 'js-cookie';
|
||||
import { useCookie } from '../src';
|
||||
|
||||
const setup = (cookieName: string) => renderHook(() => useCookie(cookieName));
|
||||
|
||||
it('should have initial value of null if no cookie exists', () => {
|
||||
const { result } = setup('some-cookie');
|
||||
|
||||
expect(result.current[0]).toBeNull();
|
||||
});
|
||||
|
||||
it('should have initial value of the cookie if it exists', () => {
|
||||
const cookieName = 'some-cookie';
|
||||
const value = 'some-value';
|
||||
Cookies.set(cookieName, value);
|
||||
|
||||
const { result } = setup(cookieName);
|
||||
|
||||
expect(result.current[0]).toBe(value);
|
||||
|
||||
// cleanup
|
||||
Cookies.remove(cookieName);
|
||||
});
|
||||
|
||||
it('should update the cookie on call to updateCookie', () => {
|
||||
const spy = jest.spyOn(Cookies, 'set');
|
||||
|
||||
const cookieName = 'some-cookie';
|
||||
const { result } = setup(cookieName);
|
||||
|
||||
const newValue = 'some-new-value';
|
||||
act(() => {
|
||||
result.current[1](newValue);
|
||||
});
|
||||
|
||||
expect(result.current[0]).toBe(newValue);
|
||||
expect(spy).toHaveBeenCalledTimes(1);
|
||||
expect(spy).toHaveBeenCalledWith(cookieName, newValue, undefined);
|
||||
|
||||
// cleanup
|
||||
spy.mockRestore();
|
||||
Cookies.remove(cookieName);
|
||||
});
|
||||
|
||||
it('should delete the cookie on call to deleteCookie', () => {
|
||||
const cookieName = 'some-cookie';
|
||||
const value = 'some-value';
|
||||
Cookies.set(cookieName, value);
|
||||
|
||||
const spy = jest.spyOn(Cookies, 'remove');
|
||||
|
||||
const { result } = setup(cookieName);
|
||||
|
||||
expect(result.current[0]).toBe(value);
|
||||
|
||||
act(() => {
|
||||
result.current[2]();
|
||||
});
|
||||
|
||||
expect(result.current[0]).toBeNull();
|
||||
expect(spy).toHaveBeenCalledTimes(1);
|
||||
expect(spy).toHaveBeenLastCalledWith(cookieName);
|
||||
|
||||
// cleanup
|
||||
spy.mockRestore();
|
||||
Cookies.remove(cookieName);
|
||||
});
|
||||
10
yarn.lock
10
yarn.lock
@ -2929,6 +2929,11 @@
|
||||
dependencies:
|
||||
jest-diff "^24.3.0"
|
||||
|
||||
"@types/js-cookie@^2.2.4":
|
||||
version "2.2.4"
|
||||
resolved "https://registry.yarnpkg.com/@types/js-cookie/-/js-cookie-2.2.4.tgz#f79720b4755aa197c2e15e982e2f438f5748e348"
|
||||
integrity sha512-WTfSE1Eauak/Nrg6cA9FgPTFvVawejsai6zXoq0QYTQ3mxONeRtGhKxa7wMlUzWWmzrmTeV+rwLjHgsCntdrsA==
|
||||
|
||||
"@types/lolex@^2.1.3":
|
||||
version "2.1.3"
|
||||
resolved "https://registry.yarnpkg.com/@types/lolex/-/lolex-2.1.3.tgz#793557c9b8ad319b4c8e4c6548b90893f4aa5f69"
|
||||
@ -8787,6 +8792,11 @@ jest@24.9.0:
|
||||
import-local "^2.0.0"
|
||||
jest-cli "^24.9.0"
|
||||
|
||||
js-cookie@^2.2.1:
|
||||
version "2.2.1"
|
||||
resolved "https://registry.yarnpkg.com/js-cookie/-/js-cookie-2.2.1.tgz#69e106dc5d5806894562902aa5baec3744e9b2b8"
|
||||
integrity sha512-HvdH2LzI/EAZcUwA8+0nKNtWHqS+ZmijLA30RwZA0bo7ToCckjK5MkGhjED9KoRcXO6BaGI3I9UIzSA1FKFPOQ==
|
||||
|
||||
js-levenshtein@^1.1.3:
|
||||
version "1.1.6"
|
||||
resolved "https://registry.yarnpkg.com/js-levenshtein/-/js-levenshtein-1.1.6.tgz#c6cee58eb3550372df8deb85fad5ce66ce01d59d"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user