- Published on
- -β³4 mins read
How to Create a Type-Safe, Flexible useCookie Hook in TypeScript
- Authors
- Name
- Seraj Vahdati
- @seraj
When working with client-side cookies in React, managing state alongside cookie values can sometimes be tricky. You might want a cookie's value to persist across sessions, or update it dynamically based on user interactions. Additionally, ensuring type safety in a TypeScript project adds another layer of complexity. Today, we'll walk through creating a custom useCookie
hook in TypeScript that is both type-safe and flexible, making it easy to manage cookies in your React applications.
Why Create a Custom Hook?
While there are libraries like js-cookie
that handle cookie operations elegantly, integrating these with React's state management requires some extra work. A custom hook allows you to:
- Synchronize State: Keep a cookie's value in sync with React's state.
- Ensure Type Safety: Use TypeScript to enforce type checks and avoid runtime errors.
- Abstract Cookie Management: Simplify cookie operations with a reusable hook.
Let's dive into the implementation of a useCookie
hook that meets these requirements.
useCookie
Hook in TypeScript
The Hereβs how the useCookie
hook is implemented:
import { useState, useCallback } from 'react'import Cookies, { CookieAttributes } from 'js-cookie'
// Define the return type of the hooktype UseCookieReturn<T> = [ T | null, // Value of the cookie (newValue: T, options?: CookieAttributes) => void, // Function to update the cookie () => void // Function to delete the cookie]
export default function useCookie<T>(name: string, defaultValue: T): UseCookieReturn<T> { const [value, setValue] = useState<T | null>(() => { const cookie = Cookies.get(name) if (cookie) { try { // Attempt to parse JSON if the cookie is a stringified object return JSON.parse(cookie) as T } catch (error) { // If parsing fails, return the raw cookie string return (cookie as unknown) as T } } // If no cookie exists, set and return the default value Cookies.set(name, JSON.stringify(defaultValue)) return defaultValue })
const updateCookie = useCallback( (newValue: T, options?: CookieAttributes) => { // Stringify the value before storing it Cookies.set(name, JSON.stringify(newValue), options) setValue(newValue) }, [name] )
const deleteCookie = useCallback(() => { Cookies.remove(name) setValue(null) }, [name])
return [value, updateCookie, deleteCookie]}
useCookie
Hook
Key Features of the -
Type Safety: The hook is generic (
<T>
), allowing you to specify the type of the cookie value. This is particularly useful when storing objects or arrays in cookies, as it ensures that your code remains type-safe and reduces the risk of runtime errors.const [user, setUser, deleteUser] = useCookie<User>('user', defaultUser) -
JSON Parsing: By default, cookies store values as strings. However, many applications need to store more complex data structures, such as objects or arrays. The
useCookie
hook attempts to parse the cookie value as JSON, allowing you to store and retrieve structured data easily. If the cookie value is not valid JSON, the hook safely returns the raw string value. -
Cookie Attributes: The
updateCookie
function accepts an optionaloptions
parameter of typeCookieAttributes
, allowing you to configure cookie settings likeexpires
,path
,secure
, andsameSite
.updateCookie(newUser, { expires: 7 }) -
Default Value Handling: If the specified cookie does not exist, the hook sets and returns a default value. This ensures that your application behaves predictably, even when cookies are missing or have expired.
useCookie
Hook
Using the Now that we've built the useCookie
hook, let's see how it can be used in a React component.
import React from 'react'import useCookie from './useCookie'
interface User { name: string age: number}
const defaultUser: User = { name: 'John Doe', age: 30 }
function UserProfile() { const [user, setUser, deleteUser] = useCookie<User>('user', defaultUser)
const handleUpdateUser = () => { setUser({ name: 'Jane Smith', age: 25 }, { expires: 7 }) }
const handleDeleteUser = () => { deleteUser() }
return ( <div> <h1>User Profile</h1> <p>Name: {user?.name}</p> <p>Age: {user?.age}</p> <button onClick={handleUpdateUser}>Update User</button> <button onClick={handleDeleteUser}>Delete User</button> </div> )}
export default UserProfile
Conclusion
With this custom useCookie
hook, you now have a powerful tool to manage cookies in your React applications with ease and confidence. The hook's type safety, JSON parsing, and support for cookie attributes make it a flexible solution for a wide range of use cases. By encapsulating cookie management in a reusable hook, your codebase becomes cleaner and easier to maintain.
Next time you need to manage cookies in a React project, consider using this useCookie
hook to simplify your code and improve type safety.