-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Bound/global mutate functions do not mutate remote data #2971
Comments
When you call In the following case, the fetcher is called again. const { data, mutate } = useSWR<{ count: number }>("/count", fetcher);
return (
<div>
<span>Count: {data?.count ?? ""}</span>
<button onClick={(() => {
mutate({ count: data.count + 1 });
}}>
Increment
</button>
</div>
) If you want to make a remote mutation, you have to call it manually. const updateCount = (count) => {
return fetch("/count", {
method: "PATCH",
body: JSON.stringify(count),
headers: { "Content-Type": "application/json" },
});
}
mutate(() => updateCount(newCount); |
@koba04 Thanks for the response! I think you're right that the behavior of In the bound mutate section of the docs, the only example shows an updater being called separately from the // send a request to the API to update the data
await requestUpdateUsername(newName)
// update the local data immediately and revalidate (refetch)
// NOTE: key is not required when using useSWR's mutate as it's pre-bound
mutate({ ...data, name: newName }) That example seems clearly suboptimal: It implies two network requests (the update followed by a revalidation) when you should only need one, the UI doesn't respond to the user's click until after the update request has completed, and there's no failure handling. Then if you scroll down to the API parameters section, the docs describe the
If IMO it would make more sense for the docs to present a
I'd be happy to contribute a draft if other folks feel the same way. |
Agree with this, I found this pretty confusing. It also is odd that the TypeScript types expect the remote mutation function to return valid data for the |
Bug report
I'm a longtime SWR user, but I'm still puzzled by the behavior of the three different mutate functions:
useSWR
.useSWRConfig
or withimport { mutate } from "swr"
.useSWRMutation
.The docs seem to describe these three functions as three ways to achieve the same goal: mutating data. When I hear "mutating data" in the context of a framework like SWR, I assume that the goal is to update data both remotely and locally, either via an optimistic update (update the local data immediately and revert it if the remote update fails) or a pessimistic update (wait to update the local data until the remote update is confirmed).
However, in practice it seems that only
useSWRMutation
performs remote updates. The other two mutation functions only affect local state, which creates an inconsistency with the remote state.That means that you get some very strange behavior by default: If you use the bound or global mutate function to perform an update, with no additional parameters, then that update will be reverted moments later when revalidation occurs.
Description / Observed Behavior
Let's look at an example (a simplified version of the CodeSandbox below):
This looks like a straightforward use of the bound mutate function. However, if you click the button, the count will go up by 1, then back down to its original value when revalidation occurs, because the remote state is not modified.
Expected Behavior
I'd expect the bound and global mutate functions to trigger the fetcher to modify the remote state, like
useSWRMutation
does. The optimistic updates example in the docs seems to show the global mutate function being used in this way, but I've never been able to get it to work; is there something I'm missing?Alternatively, I'd expect the docs to be very clear that the bound and global mutate functions are only useful when you're making the remote update separately, and that
useSWRMutation
is the preferred way of performing mutations.Repro Steps / Code Example
This CodeSandbox demonstrates how the three mutation functions behave in a very simple scenario: https://codesandbox.io/p/devbox/focused-euler-sp668n?file=%2Fapp%2Fpage.tsx%3A20%2C14
Additional Context
SWR version: 2.2.5
The text was updated successfully, but these errors were encountered: