use-cookie-state
Version:
State management React hook using browser cookies as persistent storage
242 lines (181 loc) • 7.9 kB
Markdown
# use-cookie-state
A simple, yet flexible React hook for managing persistent state through browser cookies.
By leveraging browser cookies, `use-cookie-state` ensures that your component states remain consistent and available even after a page reload. It gracefully handles both client and server-side rendering (SSR) scenarios.
**Key Highlights**:
- **Persistent state**: Store your React state in browser cookies.
- **Similar to `useState`**: Familiar API and usage, making it intuitive for React developers.
- **Flexible options**: Customizable cookie settings, including `maxAge`, `expires`, `domain`, `path`, `secure`, `httpOnly`, `sameSite`, `priority`, and `partitioned`.
- **SSR-friendly**: Falls back to `useState` behavior when `document.cookie` is not accessible.
[](https://www.npmjs.com/package/use-cookie-state)
[](https://codecov.io/gh/dqunbp/use-cookie-state)
## Table of Contents
- [use-cookie-state](#use-cookie-state)
- [Table of Contents](#table-of-contents)
- [Installation](#installation)
- [API Reference](#api-reference)
- [Cookie Options](#cookie-options)
- [Default Encode Options:](#default-encode-options)
- [Other Encode Options:](#other-encode-options)
- [Examples](#examples)
- [Basic Usage](#basic-usage)
- [Handling Complex Data (JSON)](#handling-complex-data-json)
- [Custom Cookie Settings](#custom-cookie-settings)
- [Runtime Overrides](#runtime-overrides)
- [Server-Side Rendering (SSR)](#server-side-rendering-ssr)
- [Tips \& Best Practices](#tips--best-practices)
- [License](#license)
---
## Installation
**Using npm:**
```bash
npm install --save use-cookie-state cookie
```
**Using yarn:**
```bash
yarn add use-cookie-state cookie
```
> **Note:** The `cookie` package is a peer dependency and must be installed alongside `use-cookie-state`.
---
## API Reference
```ts
useCookieState<T = string>(
key: string,
initialValue: T,
options?: {
decode?: (value: string) => any;
encode?: CookieSerializeOptions;
}
): [T, (value: T, encode?: CookieSerializeOptions) => void];
```
**Parameters:**
- **key** (*string*, required): Cookie name.
- **initialValue** (*T*, required): Initial state value. Can be a primitive, object, or a function returning the initial value.
- **options** (optional):
- **decode**: A function to decode the cookie value when reading it from `document.cookie`.
- **encode**: An object specifying default cookie attributes used when writing the cookie.
**!IMPORTANT!**: Due the `cookie` package implementation, the `decode` function will be applied for each cookie value, during the cookies parsing process. Be patient to use try/catch block to avoid errors.
**Return Value:**
- An array `[value, setValue]` similar to `useState`:
- **value**: The current state derived from the cookie.
- **setValue(value: T, encode?: CookieSerializeOptions)**: Updates the cookie (and the state). Accepts optional runtime `encode` options to override defaults.
---
## Cookie Options
When setting or updating cookies, you can specify cookie-related attributes as `encode` options. These options influence how the cookie is stored and retrieved by the browser. All cookie attributes are optional.
### Default Encode Options:
If no `encode` options are provided, `use-cookie-state` defaults to:
```js
{ path: "/", expires: new Date("9999") }
```
> You can override these defaults by specifying your own `encode` options.
### Other Encode Options:
- **maxAge** (number): Maximum age of the cookie in seconds. If both `expires` and `maxAge` are set, `maxAge` takes precedence.
- **expires** (Date): Specific date and time when the cookie should expire.
- **domain** (string): The domain for which the cookie is valid. Defaults to the current domain if not set.
- **path** (string): The path for which the cookie is valid. Defaults to `"/"`.
- **httpOnly** (boolean): If `true`, the cookie is not accessible to client-side JavaScript.
- **secure** (boolean): If `true`, the cookie is only sent over HTTPS connections.
- **sameSite** (`true | "strict" | "lax" | "none"`): Controls cross-site request behavior.
- `true` or `"strict"`: Strict same-site enforcement.
- `"lax"`: Lax same-site enforcement.
- `"none"`: No same-site restrictions.
- **priority** (`"low" | "medium" | "high"`): Sets the cookie’s priority.
- **partitioned** (boolean): Enables the `Partitioned` attribute for the cookie (experimental).
> You can find more details about these options in the cookie package documentation: [CookieSerializeOptions](https://www.npmjs.com/package/cookie#options-1).
---
## Examples
### Basic Usage
```jsx
import React from "react";
import { useCookieState } from "use-cookie-state";
function MyComponent() {
const [value, setValue] = useCookieState("username", "JohnDoe");
return (
<div>
<div>Username: {value}</div>
<button onClick={() => setValue("JaneDoe")}>Change Username</button>
</div>
);
}
export default MyComponent;
```
### Handling Complex Data (JSON)
For objects/arrays, store as JSON and provide a `decode` function:
```jsx
import React from "react";
import { useCookieState } from "use-cookie-state";
function jsonDecode(value) {
try {
return JSON.parse(value);
} catch {
return value;
}
}
function MyComponent() {
const [data, setData] = useCookieState("myData", { foo: "bar" }, { decode: jsonDecode });
const updateData = () => {
setData({ foo: "baz", count: 1 });
};
return (
<div>
<pre>{JSON.stringify(data, null, 2)}</pre>
<button onClick={updateData}>Update Data</button>
</div>
);
}
export default MyComponent;
```
**!IMPORTANT!**: Due the `cookie` package implementation, the `decode` function will be applied for each cookie value, during the cookies parsing process. Be patient to use try/catch block to avoid errors.
### Custom Cookie Settings
```jsx
import React from "react";
import { useCookieState } from "use-cookie-state";
function MyComponent() {
const [value] = useCookieState("myKey", "initialVal", {
encode: {
maxAge: 60 * 60 * 24 * 7, // 1 week
secure: true,
sameSite: "strict",
httpOnly: true
}
});
return <div>Value: {value}</div>;
}
export default MyComponent;
```
### Runtime Overrides
```jsx
import React from "react";
import { useCookieState } from "use-cookie-state";
function MyComponent() {
const [state, setState] = useCookieState("userToken", "abc123", {
encode: { secure: true, path: "/" }
});
const updateToken = () => {
// Add domain at runtime, merging it with the default secure and path options
setState("newTokenValue", { domain: "example.com" });
};
return (
<div>
<div>Current Token: {state}</div>
<button onClick={updateToken}>Update Token</button>
</div>
);
}
export default MyComponent;
```
---
## Server-Side Rendering (SSR)
On the server, `document.cookie` is not available. During SSR:
- `useCookieState` uses the provided `initialValue` directly, just like `useState`.
- No cookie operations occur until the browser environment is available.
Once hydrated, it will sync the component state with any browser cookies.
---
## Tips & Best Practices
1. **Keep cookie size small**: Most cookies have size limits (~4KB).
2. **Use JSON for complex data**: Consider `JSON.stringify` on write and a custom `decode` function on read.
3. **Security considerations**: Use `secure: true` if your site uses HTTPS.
4. **Domain and path**: Control where cookies are valid with `domain` and `path`.
5. **SameSite attribute**: Consider `sameSite` to protect against CSRF attacks or to allow cross-site requests depending on your needs.
---
## License
MIT © [dqunbp](https://github.com/dqunbp)