-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Open
Description
Bug report
Description / Observed Behavior
When using mutate() with both optimisticData and an async data function that return structurally identical data (but different references), SWR triggers two renders even though the data content is the same. This causes mutations to paginated data to re-render the whole array twice.
Observed in useSWRInfinite:
const { data, mutate } = useSWRInfinite(getKey, fetcher);
// This causes TWO renders even if server returns identical data
mutate(
async (current) => {
const result = await api.addItem(item);
return [...result]; // New reference #1
},
{
optimisticData: (current) => [...current, item], // New reference #2
revalidate: false
}
);Result:
- First render with optimisticData array
- Second render with final data array (even though contents are identical)
Expected Behavior
SWR should use compare() function in mutation paths. When the final data from a mutation is structurally identical to the current cached data (including optimistic data), SWR should return the existing reference to avoid a cache update and match the revalidation.
Repro Steps / Code Example
import useSWRInfinite from 'swr/infinite';
function MyComponent() {
const { data, mutate } = useSWRInfinite(
(index) => `/api/items?page=${index}`,
fetcher
);
const addItem = async (item: Item) => {
// BUG: This causes two renders even if API returns the same item
await mutate(
async (currentPages) => {
const newItem = await fetch('/api/items', {
method: 'POST',
body: JSON.stringify(item)
}).then(r => r.json());
// Optimistic item and server item have same content
// but different references
return currentPages.map((page, i) =>
i === 0
? [newItem, ...page] // New reference
: page
);
},
{
optimisticData: (currentPages) =>
currentPages.map((page, i) =>
i === 0
? [item, ...page] // New reference
: page
),
revalidate: false
}
);
};
// Renders twice even though optimistic and final data are identical
return <div>{data?.[0]?.length} items</div>;
}Additional Context
SWR version: 2.3.6
Metadata
Metadata
Assignees
Labels
No labels