#swr no loading state after key change
1 messages · Page 1 of 1 (latest)
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.
@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.
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:
-
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.
-
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:
----------------------