swr icon indicating copy to clipboard operation
swr copied to clipboard

Add `isMutated` boolean to track local mutations

Open nicholaschiang opened this issue 2 years ago • 0 comments

Bug report

Description / Observed Behavior

SWR sometimes accidentally revalidates locally mutated data (i.e. data that has been mutated locally without revalidation but isn't yet saved in our database which causes undesired state wipes when SWR revalidates after an e.g. switched tab).

Expected Behavior

SWR should keep track of local mutations per key and then return a boolean value isMutated that indicates:

  • true - The current data was the result of a local mutation that wasn't actually fetched from the back-end.
  • false - The current data is the response from a fetch request.

Repro Steps / Code Example

For example:

const { data, isMutated, isValidating, mutate } = useSWR('/api/account');
// 1) data = undefined, isMutated = false, isValidating = true
// 2) data is fetched from `/api/account` successfully
// 3) data = serverAccount, isMutated = false, isValidating = false
await mutate(updatedAccount, false);
// 4) data = updatedAccount, isMutated = true, isValidating = false
await mutate(updatedAccount, true);
// 5) data = updatedAccount, isMutated = true, isValidating = true
// 6) revalidation from `/api/account` occurs successfully
// 7) data = serverAccount, isMutated = false, isValidating = false

Additional Context

SWR version: 0.5.6 Add any other context about the problem here.

I have an infinite scrolling UI that determines whether or not there is more data to load by the length of the last server response (for /api/messages). Each full "page" of data contains 5 messages. Thus, I know that there's no more data to load if the last server response has a length of less than (<) 5 messages. However, if the user locally mutates that last page data and changes its length (e.g. to archive a message which removes it from the feed), I can no longer rely on it to determine if there's more data to be loaded. If I had this isMutated boolean value, however, I could simply have an OR statement:

hasMore={isMutated || data[data.length - 1].length === 5} // The infinite scroller has more messages to show.

nicholaschiang avatar Jul 31 '21 01:07 nicholaschiang