Skip to content

[Docs]: createCookie().parse() returns empty object for plain cookies set from client-side JavaScript #14685

@JYunth

Description

@JYunth

Describe what's incorrect/missing in the documentation

Summary

When setting a cookie from client-side JavaScript using document.cookie, the server-side createCookie().parse() returns an empty object instead of the cookie value, even though the cookie header is correctly received.

Reproduction

1. Create cookie utility (app/lib/theme.server.ts)

import { createCookie } from "react-router";
export const themeCookie = createCookie("theme", {
  maxAge: 60 * 60 * 24 * 365,
  httpOnly: false,
  secure: process.env.NODE_ENV === "production",
  sameSite: "lax",
  path: "/",
});

export async function getTheme(request: Request): Promise<string | null> {
  const cookieHeader = request.headers.get("Cookie");
  console.log("Cookie header:", cookieHeader);

  const parsed = await themeCookie.parse(cookieHeader);
  console.log("Parsed:", parsed);

  return parsed;
}

2. Set cookie from client (app/components/theme-toggle.tsx)

const toggleTheme = () => {
  const newTheme = theme === "light" ? "dark" : "light";

  // Set plain cookie from client
  document.cookie = `theme=${newTheme}; path=/; max-age=31536000; SameSite=Lax`;

  revalidator.revalidate();
};

3. Observe server logs

Cookie header: theme=dark; __session=eyJ1c2VySWQi...
Parsed: {}

Expected Behavior

createCookie().parse() should return "dark" or the cookie value.

Actual Behavior

Returns empty object {} despite cookie being present in header.

Workaround

Manual cookie parsing works:

const cookies = cookieHeader.split(';').reduce((acc, cookie) => {
    const [key, value] = cookie.trim().split('=');
    acc[key] = value;
    return acc;
  }, {} as Record<string, string>);
  const theme = cookies.theme; // Works!

Environment

  • React Router: v7 (latest)
  • SSR: enabled
  • Node: v20+

Is createCookie().parse() only intended to work with signed/sealed cookies created by the framework? If so, this should be documented. If plain cookies should work, this appears to be a bug.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions