#swr no loading state after key change

1 messages · Page 1 of 1 (latest)

cursive walrus
#

const { data, error, isLoading } = useSWR<ActivitiesGeneral[], Error>("/general/activities?after=" + after.getTime()

swr no loading state after key change (e.g. after changes value, isLoading does not go true anymore
)

gilded cairnBOT
#

Hi @cursive walrus. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave:

#

You're experiencing an issue with SWR where the isLoading state doesn't update when the key changes (in your case, when the after parameter changes). This is a known behavior in Next.js applications when using SWR for client-side data fetching.

Why this happens

When you update a parameter in the SWR key (like your timestamp parameter), SWR doesn't show the loading state for subsequent fetches after the initial load. This is because SWR is designed to avoid showing loading states during transitions to prevent unwanted UI flickering.

Solutions

There are several approaches to handle this:

1. Use React's useTransition hook

You can wrap your navigation or parameter changes in React's useTransition hook to show a loading indicator:

import { useTransition } from "react";
import { useRouter } from "next/navigation";

// Inside your component
const [isPending, startTransition] = useTransition();
const router = useRouter();

const navigate = useCallback((newTimestamp) => {
    startTransition(() => {
        router.push(`/your-path?after=${newTimestamp}`);
    });
});

// Then in your JSX
return (
    <>
        {isPending && <LoadingIndicator />}
        {/* Your content */}
    </>
);

This approach is recommended by users in the Next.js community for handling loading states when updating search parameters Github Issue #49297.

2. Use SWR's built-in states

SWR provides other states you can use:

const { data, error, isLoading, isValidating } = useSWR(
  "/general/activities?after=" + after.getTime(),
  fetcher
);

The isValidating flag will be true during revalidation, even for subsequent fetches, which might be more suitable for your use case.

3. Key-based approach with Suspense (if using Suspense mode)

#

If you're using SWR with Suspense, you can add a key to your Suspense component that changes when your parameters change:

<Suspense 
  key={`activities-${after.getTime()}`} 
  fallback={<LoadingComponent />}
>
  <YourDataComponent after={after} />
</Suspense>

This forces React to show the fallback when the key changes Github Issue #62049.

Best Practice

For client-side data fetching in Next.js, SWR is recommended over plain useEffect approaches as it handles caching, revalidation, and other features automatically Next.js Client-side Fetching Docs.

If you need more granular control over loading states during parameter changes, the useTransition approach is currently the most reliable solution.

Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:

#

@cursive walrus Kapa.ai is still learning and improving, please let me know how I did by reacting below.

cursive walrus
#

@gilded cairn it seems this is related to how react renders. I have a component which is passed the isLoading as a prop, and if I console.log(isLoading) it does change, but react doesn't rerender the component.

gilded cairnBOT
#

Let me check the knowledge base for you again. Give me one moment! :books:

#

You're right - this is related to how React renders components. If you're seeing isLoading change in your console logs but your component isn't re-rendering, there are a few possible explanations:

Component Re-rendering Issues

This behavior is similar to issues observed with loading states in Next.js, particularly with components that should update based on changing props. From the knowledge sources, we can see several patterns where components don't re-render as expected:

  1. React's Suspense Behavior: React won't re-trigger Suspense boundaries that have already shown their fallback unless the whole subtree is remounted. This is documented in several GitHub issues where loading components don't re-render on navigation or data changes Github Issue #69089.

  2. Component Initialization: In some cases, components get stuck in their initial state and don't update when props change Github Issue #73568.

Solutions to Try

Here are some approaches to fix your component re-rendering issue:

1. Force Re-mounting with Keys

Add a key to your component that changes when your data changes:

<YourComponent 
  key={`component-${someChangingValue}`} 
  isLoading={isLoading} 
/>

This forces React to completely unmount and remount the component when the key changes, ensuring it gets the new props.

2. Use State in the Child Component

Instead of relying solely on props, consider using the prop to initialize local state in your component:

"use client";
import { useState, useEffect } from 'react';
#

function YourComponent({ isLoading: isLoadingProp }) {
const [isLoading, setIsLoading] = useState(isLoadingProp);

useEffect(() => {
setIsLoading(isLoadingProp);
}, [isLoadingProp]);

// Now use isLoading from state
return (
<div>
{isLoading ? <LoadingIndicator /> : <Content />}
</div>
);
}


### 3. Check for Memoization Issues

If your component is wrapped in `React.memo()` or uses `useMemo`, it might not re-render when you expect. Make sure your dependency arrays include all values that should trigger re-renders.

### 4. Component Hierarchy Considerations

The issue might be related to how Next.js handles component hierarchies, especially with loading states. As seen in [Github Issue #66029](<https://github.com/vercel/next.js/issues/66029>), there can be component reinitialization issues with loading components and revalidation.

If you're using a complex component hierarchy with nested routes or layouts, this could affect how your loading states propagate through the component tree.

These approaches should help address the issue where your component isn't re-rendering despite the `isLoading` prop changing. The key-based approach is often the simplest solution if you need an immediate fix.
----------------------
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
----------------------