loading...
Cover image for Store state in cookies with use-cookie-state React hook

Store state in cookies with use-cookie-state React hook

dqunbp profile image dqunbp Updated on ・3 min read

🤔 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 or theme.

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;
}
Enter fullscreen mode Exit fullscreen mode

⚙️ 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];
}
Enter fullscreen mode Exit fullscreen mode

⚙️ 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:

ℹ️ As you can see, there is another .? operator here, called the ʻoptional chaining operator.
It avoids errors like ʻUncaught TypeError: Cannot read property 'prop_name' of undefined
, returning simply ʻundefined` in this case, you can read more about it here

🎆 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!

🍪 https://github.com/dqunbp/use-cookie-state 🍪

Discussion

pic
Editor guide