Skip to content
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

Batch revalidation requests together #482

Closed
nicholaschiang opened this issue Jun 21, 2020 · 2 comments · Fixed by #1549
Closed

Batch revalidation requests together #482

nicholaschiang opened this issue Jun 21, 2020 · 2 comments · Fixed by #1549
Labels
feature request New feature or request

Comments

@nicholaschiang
Copy link

nicholaschiang commented Jun 21, 2020

Bug report

Description / Observed Behavior

What kind of issues did you encounter with SWR?

I have a live updating profile view. Whenever there's a change in one of the profile's TextFields, I mutate the local data immediately and send a request to update their profile and re-validate:

await mutate('/api/account', updatedUser.toJSON(), false);
await mutate('/api/account', axios.put('/api/account', updatedUser.toJSON(), false);

Note: The /api/account endpoint already returns the updated user profile (after server-side validation), so we don't really "re-validate" at all. This is the pattern described in this issue and the documentation.

Because that last mutate call occurs far after the user made the change, it "re-types" what happened (this is expected, but not ideal):

swr-batching-error

Expected Behavior

How did you expect SWR to behave here?

SWR should batch together re-validation requests that contain promises (much like how React batches together DOM/state updates).

Mutate calls that are not promises should be immediate:

await mutate('/api/account', updateUser.toJSON(), false);

Mutate calls that have promises should be batched together (i.e. when a new Promise comes along, cancel/ignore all the previous ones (that are still pending) and mutate based only on the resolution of that most recent Promise):

await mutate('/api/account', axios.put('/api/account', updatedUser.toJSON()), false);

Additional Context

SWR version. ^0.2.2
Add any other context about the problem here.

My current solution is to just update the data locally, perform the PUT request to update the database record, and then re-validate once all of the requests have gone through and there hasn't been another change within 500ms:

const timeoutId = React.useRef<ReturnType<typeof setTimeout>>();

if (timeoutId.current) clearTimeout(timeoutId.current);
await mutate('/api/account', newUser.toJSON(), false);
if (!newUser.id) {
  console.warn('[WARNING] Cannot update user without ID.');
} else {
  const url = `/api/users/${newUser.id}`;
  await axios.put<UserJSON>(url, newUser.toJSON());
  timeoutId.current = setTimeout(() => mutate('/api/account'), 500);
}

That behavior, while not ideal, looks like this:

proper-swr-batching-behavior

@shuding shuding added the feature request New feature or request label Oct 13, 2021
@shuding
Copy link
Member

shuding commented Oct 13, 2021

I think this is already fixed in the latest version of SWR, opened #1549 to add a test case for it.

@shuding shuding closed this as completed Oct 13, 2021
@shuding
Copy link
Member

shuding commented Oct 13, 2021

(Thanks for the detailed issue report, really appreciate it!)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature request New feature or request
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants