Telerik blogs

Learn how the Cookie Store API modernizes cookie management with async operations and event handling for efficient, error-free web development.

The browser Cookie Store API represents a modern approach to handling cookies in web applications. The way we’ve always done it is using document.cookie which is error-prone because you have to work with key/value pairs in a string. Besides being error-prone, it’s a synchronous, blocking operation, which doesn’t fit modern patterns whereby we try to move certain operations to be asynchronous and out of the main thread. It depends on the document object, therefore it can’t be used in a Service Worker context.

This tutorial explores how this new API simplifies cookie management. We’ll build a site with light and dark themes, allowing users to switch themes and store their preferences in a cookie for future visits.

Traditionally, web developers have used the document.cookie API to work with cookies. Here’s how we used to handle cookies:

// Setting a cookie
document.cookie = "theme=dark; expires=Fri, 31 Dec 2024 23:59:59 GMT; path=/";

// Reading cookies
function getCookie(name) {
    const value = `; ${document.cookie}`;
    const parts = value.split(`; ${name}=`);
    if (parts.length === 2) return parts.pop().split(';').shift();
}

// Using the cookie
const theme = getCookie('theme');
if (theme === 'dark') {
    document.body.classList.add('dark-theme');
}

At first glance, setting cookies with document.cookie feels like we’re overwriting the entire cookie value. The string manipulation needed to read a cookie value is cumbersome, and a small mistake can break your application. Handling multiple cookies means parsing the cookie string over and over, and due to its synchronous nature, this could slow down your application.

The Cookie Store API on the other hand addresses those issues by providing a promise-based interface with these advantages:

  • Cleaner, more intuitive methods for reading and writing cookies
  • Built-in event handling for cookie changes
  • Asynchronous operations that don’t block the main thread
  • Methods to handle multiple cookies efficiently

Let’s see how to build a theme switcher that demonstrates how to use the Cookie Store API. Our example will allow users to toggle between light and dark themes, with their preference persisting across page reloads and browser sessions.

First, let’s look at the HTML structure:

<div class="container">
    <h1>CookieStore API Demo</h1>
    <button class="theme-switcher" onclick="toggleTheme()">Toggle Theme</button>
    <div class="cookie-info">
        <h3>Current Cookie State:</h3>
        <div id="cookieDisplay"></div>
    </div>
</div>

Now, let’s implement the core functionality using the CookieStore interface:

// Check if CookieStore API is supported
if ('cookieStore' in window) {
    // Listen for cookie changes
    cookieStore.addEventListener('change', event => {
        console.log('Cookie change detected:', event);
        updateCookieDisplay();
    });
}

// Initialize theme on page load
async function initializeTheme() {
    try {
        const themeCookie = await cookieStore.get('theme');
        if (themeCookie && themeCookie.value === 'dark') {
            document.body.classList.add('dark-theme');
        }
        updateCookieDisplay();
    } catch (error) {
        console.error('Error reading theme cookie:', error);
    }
}

// Toggle theme and save preference
async function toggleTheme() {
    const isDarkTheme = document.body.classList.toggle('dark-theme');
    
    try {
        await cookieStore.set({
            name: 'theme',
            value: isDarkTheme ? 'dark' : 'light',
            expires: Date.now() + 30 * 24 * 60 * 60 * 1000, // 30 days
            sameSite: 'strict'
        });
    } catch (error) {
        console.error('Error saving theme preference:', error);
    }
}

Let’s break down the key features:

  1. Async/Await Pattern: The API uses promises, making it compatible with async/await syntax. This results in cleaner code compared to callback-based approaches.

  2. Cookie Change Detection: The CookieStore interface provides an event listener for listening to cookie changes. This allows us to react to cookie modifications in real-time.

  3. Simplified Reading and Writing: Notice how we can directly get and set cookies using methods like set(), get() and getAll() without string manipulation.

Here’s the complete code for you to try yourself and a demo of how it works.

Demo showing how the toggle switch works with CookieStore

Browser Support and Fallbacks

As of 2024, the CookieStore API is not universally supported across all browsers. Chrome and Edge support it, while Firefox and Safari are still working on implementation.

Image showing browser compatibility for Cookie Store API

Image from MDN

For production applications, you should implement a fallback mechanism. You should check if cookieStore is available in the Window object. Here’s an example:

class CookieManager {
    constructor() {
        this.useModernAPI = 'cookieStore' in window;
    }

    async setCookie(name, value, options = {}) {
        if (this.useModernAPI) {
            return cookieStore.set({ name, value, ...options });
        }
        
        // Fallback to traditional approach
        let cookie = `${name}=${value}`;
        if (options.expires) {
            cookie += `; expires=${new Date(options.expires).toUTCString()}`;
        }
        if (options.path) {
            cookie += `; path=${options.path}`;
        }
        document.cookie = cookie;
    }

    async getCookie(name) {
        if (this.useModernAPI) {
            return cookieStore.get(name);
        }
        
        // Fallback implementation
        const value = `; ${document.cookie}`;
        const parts = value.split(`; ${name}=`);
        if (parts.length === 2) {
            return { 
                name, 
                value: parts.pop().split(';').shift() 
            };
        }
        return null;
    }
}

This example defines a class with two methods getCookie() and setCookie(). These methods use the CookieStore methods if available; otherwise, they fall back to document.cookie.

Wrap-up

The Cookie Store API significantly improves cookie handling. Its promise-based interface, built-in change detection and cleaner methods make it a powerful tool for modern web development. While browser support is still growing, implementing it with appropriate fallbacks allows you to write durable code while being future-ready. Check the MDN documentation for more information about the Cookie Store API.


Peter Mbanugo
About the Author

Peter Mbanugo

Peter is a software consultant, technical trainer and OSS contributor/maintainer with excellent interpersonal and motivational abilities to develop collaborative relationships among high-functioning teams. He focuses on cloud-native architectures, serverless, continuous deployment/delivery, and developer experience. You can follow him on Twitter.

Related Posts

Comments

Comments are disabled in preview mode.