question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

useLoaderData returns stale data

See original GitHub issue

What version of Remix are you using?

1.6.0

Steps to Reproduce

Here is a sample repository: https://github.com/jaschaio/remix-use-loader-data.git

The only files changed after running npx create-remix@latest are:

  • /app/routes/index.jsx
  • /app/routes/login.jsx
  • /app/routes/logout.jsx
  • /app/root.jsx

The /app/routes/index.jsx loader checks if a cookie exists, and otherwise redirects to /login:

export const loader = ( { request } ) => {

    const { headers } = request;

    if ( ! headers.get( 'cookie' ) )
        return new Response( null, {
            status: 301,
            headers: {
                Location: '/login',
            },
        } );

    return null;

};

The /app/routes/login.jsx route defines an action that simply set’s the cookie and redirects back to the homepage:

export const action = async ( { request } ) => {

    const formData = await request.formData();

    const { username } = Object.fromEntries( Array.from( formData.entries() ) )

    return new Response( null, {
        status: 301,
        headers: {
            Location: '/',
            'Set-Cookie': `user=${ username }; Max-Age=2592000; Path=/; SameSite=Lax`,
        },
    } );

};

And the /app/routes/logout.jsx route just defines an action that unsets the cookie:

export const action = async () => {

    return new Response( null, {
        status: 301,
        headers: {
            Location: '/',
            'Set-Cookie': `user=; Max-Age=0; Path=/; SameSite=Lax`,
        },
    } );

};

The /app/routes/index.jsx route further has a logout button, that implements a fetcher:

export default function Index() {

  const fetcher = useFetcher();

  return (
    <>
        <h1>
            Home
        </h1>
        <button type="button" onClick={ () => fetcher.submit( undefined, { method: 'post', action: '/logout' } ) }>Logout</button>
    </>
  );
}

The /app/root.jsx loader method check’s if a cookie is set and returns the username from the cookie:

export const loader = ( { request } ) => {

    const { headers } = request;

    return {
        user: ( headers.get( 'cookie' ) ) ? headers.get( 'cookie' ).split( '=' ).pop() : undefined,
    }

};

Copy the sample repository and run npm run dev. Then use any username and password to login (this is just a mock).

After you have logged in, click the “Logout” button.

It will still display “Hello $username”, because the user is still returned by the useLoaderData() call. But I can see within the browsers console network tab that the request to ?_data=root is successfully made and returns no data as expected.

Only after a hard refresh the data returned from useLoaderData is actually empty.

Expected Behavior

I would expect useLoaderData() to return the data from the last call to ?_data=root instead of stale data.

Actual Behavior

useLoaderData() returns stale data after an action is performed via fetcher.submit

Issue Analytics

  • State:closed
  • Created a year ago
  • Comments:8 (3 by maintainers)

github_iconTop GitHub Comments

3reactions
brophdawg11commented, Jun 23, 2022

Oops - sorry about that! It looks like the branch for 1.6.1 had been cut just before that got merged. It’ll go out in the next release 👍

2reactions
brophdawg11commented, Jun 28, 2022

@jaschaio Just FYI this is now out in 1.6.2-pre.3, and should go out in a 1.6.2 stable tomorrow or so

Read more comments on GitHub >

github_iconTop Results From Across the Web

Data Writes - Remix
Just like useLoaderData returns the values from the loader , useActionData will return the data from the action. It will only be there...
Read more >
Shared object between loader & action does not update after ...
I have a mock database for playing around with some loaders and actions. Here's the rough layout: const db = { key: "bar"...
Read more >
Some Thoughts on Server State in Remix - DEV Community ‍ ‍
All you have to do is return the data you need in your loaders and grab that data with ... The first way,...
Read more >
React Query meets React Router | TkDodo's blog
With React Router coming into the data fetching game, ... does the trick for returning any data we have in the cache, even...
Read more >
Data Library Integration v6.6.1 - React Router
React Router's data APIs are about when to load, mutate, and revalidate data, ... While React Router's useLoaderData returns whatever you returned from...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found