🤔 Sometimes it becomes necessary to keep the state of the application between reloads of the web page.
The most common use for this is localStorage
.
When developing an application on Next.js
, I needed to receive this data during page rendering on the server-side(SSR), localStorage
is not suitable for this purpose, so I decided to use cookies
.
☝️ A cookie can contain data upto a maximum of 4096 Bytes. If you want to support most browsers, then do not exceed 50 cookies per domain, and 4093 bytes per domain. The size of all cookies together should not exceed 4096 bytes.
🐜 Therefore, this solution is well suited for storing small data such as
language
ortheme
.
When opening a web application page, cookies
are sent to the server along with Http
request, then I can get their value and use it in SSR.
To work with cookies, I decided to use an existing solution,
choosing the most popular cookies library for reading and writing cookie values.
👏 First, let's create a helper function, to read and write cookie values - getCookieValue
import cookie from "cookie";
function getCookieValue({
key,
cookies,
options,
defaultValue,
} {
const value = cookie.parse(cookies || "", options);
return value[key] ?? defaultValue;
}
⚙️ Function arguments:
- key - a unique key with which our value will be stored in browser cookies
- cookies - the cookies themselves
- options -
cookie
parse options from cookies library - defaultValue - default value, in case a value was not found for the specified key
ℹ️ If you are not familiar with ??
operator, don't worry.
It's called nullish coalescing operator
and is similar to ||
but only returns the right side when the left side is null
or undefined
. You can read more about this here
The matter is small; it remains to implement the React Hook itself
function useCookieState(
key,
initialValue,
options
) {
const getInitialValue = () => {
// if we on the server just use an initial value
if (typeof window === "undefined") return initialValue;
// otherwise get initial cookie value from `document.cookies`
return getCookieValue({
key,
cookies: document.cookie,
options: options?.decodeOps,
defaultValue: initialValue,
});
};
// get initial state value on component mounts
const [value, setValue] = useState(getInitialValue);
// encode and save the new cookie value
const setNextValue = (value) => {
document.cookie = cookie.serialize(key, value, options?.encodeOps);
setValue(value);
};
return [value, setNextValue];
}
⚙️ Here we have a hook with three arguments:
- key - the same as in the previous function
- initialValue - the initial value for the state, the same as the default value
- options - an object with shape:
- decodeOps - parse cookies parameters
- encodeOps - serialize cookies parameters
ℹ️ As you can see, there is another ?.
operator here, called the ʻoptional chaining operator.
, returning simply ʻundefined` in this case, you can read more about it here
It avoids errors like ʻUncaught TypeError: Cannot read property 'prop_name' of undefined
🎆 That's all! 🎆
Oh yeah, I almost forgot.
For your convenience, I put the hook in a tiny library, with TypeScript support, enjoy! ✨
😊 Thank you for your attention!
Top comments (1)
Amazing library