Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Remix - Can't 'Set-Cookie' anywhere except in the response from the loader of the current route

I have the world's most basic remix app setup to try to figure out createStorageSessionCookies and it seems like they can only be set in the loader of the UI route that is calling the API.

Example:

  • Index UI route
  • API at routes/api/testApi.tsx (this is a resource route with only an action)
  • app/session.server.ts where I create the storage session cookie using createStorageSessionCookies()

If I try to set the cookie anywhere else except for the return from loader in the Index UI route, it doesn't work. If I call the testApi and try to return a response that sets the cookie, doesn't work. If I create a separate function that is called from the loader and that function returns the result of an API call and tries to set the cookie, doesn't work. It literally only works if I set the cookie in the response of the loader.

Example Index route where it works

export const loader: LoaderFunction = async ({ request }) => {
    const session = await sessionStorage.getSession(
        request.headers.get('Cookie')
    );
    session.set('cookie_example', 'thisworks');
    return json(
        { status: 'this works' },
        {
            headers: {
                'Set-Cookie': await sessionStorage.commitSession(session),
            },
        }
    );
};

export default function Index() {
    const data = useLoaderData();

    return <div>hi</div>;
}

This won't work

const setCookie = async (request: Request) => {
    const session = await sessionStorage.getSession(
        request.headers.get('Cookie')
    );
    session.set('cookie_example', 'thisdoesntwork');
    return json(
        { status: 'this doesnt work' },
        {
            headers: {
                'Set-Cookie': await sessionStorage.commitSession(session),
            },
        }
    );
}

export const loader: LoaderFunction = async ({ request }) => {
    const failFunc = await setCookie(request)
    return failFunc.json()
};

export default function Index() {
    const data = useLoaderData();

    return <div>hi</div>;
}

Also won't work trying to set them from an API route (app/routes/api/setCookie.tsx called from the loader or from a button - neither work)

export let loader: LoaderFunction = () => redirect('/');

export let action: ActionFunction = async ({ request }) => {
    const session = await sessionStorage.getSession(
        request.headers.get('Cookie')
    );
    session.set('cookie_example', 'does not work');

    return json(
        { status: 'does not work' },
        {
            headers: {
                'Set-Cookie': await sessionStorage.commitSession(session),
            },
        }
    );
};
like image 906
Connor V Avatar asked Oct 15 '25 06:10

Connor V


1 Answers

Why are you calling .json() on the response from the setCookie function, when you just return json() normally. https://remix.run/docs/en/v1/api/remix#json

like image 181
Warmpigman Avatar answered Oct 18 '25 06:10

Warmpigman