Skip to content

useSWR calls with the same key in the same component yielding different data #463

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

Closed
derindutz opened this issue Jun 14, 2020 · 9 comments · Fixed by #794
Closed

useSWR calls with the same key in the same component yielding different data #463

derindutz opened this issue Jun 14, 2020 · 9 comments · Fixed by #794
Labels
help wanted Extra attention is needed

Comments

@derindutz
Copy link

derindutz commented Jun 14, 2020

Bug report

Hi! First, I just wanted to say thank you for your work on this library 😊 It's been a ton of fun to use and has made both my development process and the product I'm working on faster.

Description / Observed Behavior

useSWR calls in the same component with the same key yield different data

Expected Behavior

I'd expect useSWR calls in the same component to yield the same data. I was using helper hooks and two helpers called useSWR with the same key. My code relied on both calls returning the same data. This led to a weird and unexpected bug that took multiple hours to figure out.

Repro Steps / Code Example

https://codesandbox.io/s/swr-test-9jcdz?file=/src/App.js

Additional Context

SWR version: 0.2.3

Thanks for your help!

@derindutz derindutz changed the title useSWR calls yielding different data Multiple useSWR calls in the same component yield different data Jun 14, 2020
@derindutz derindutz changed the title Multiple useSWR calls in the same component yield different data useSWR calls with the same key in the same component yielding different data Jun 14, 2020
@shuding shuding added the help wanted Extra attention is needed label Jun 15, 2020
@tanmaylaud
Copy link
Contributor

@derindutz, I tried the following example and found no issue.
https://codesandbox.io/s/swr-test-lb87z

I observe that when the component renders, the two results are equal. Isn't that the expected behaviour?

@derindutz
Copy link
Author

The two results eventually become equal (and visually you don't notice them being different), but as you can see if you comment the window.alert code back in, there are function runs where data !== data2, which isn't what you'd expect.

It makes it so you should be extremely careful when using useSWR in helper hooks and should probably avoid it, which is sad because the ability to reuse stateful logic is one of the most beautiful parts of React Hooks and one of the main reasons React added them.

Take this contrived example that may illustrate the problem. Say the user changes from "Derin Dutz" to "Tanmay Laud", it'll log "Derin Dutz" -> "Derin Laud" (or "Tanmay Dutz") -> "Tanmay Laud"

function useUserFirstName() {
  const {data: user} = useSWR("user")
  return user ? user.first_name : null;
}

function useUserLastName() {
  const {data: user} = useSWR("user")
  return user ? user.last_name : null;
}

function Component() {
  const firstName = useUserFirstName();
  const lastName = useUserLastName();
  useEffect(() => {
    logDataOverTheNetwork(`used component as ${firstName} ${lastName}`)
  }, [firstName, lastName]);
  return <div>{firstName} {lastName}</div>;
}

It's a leak in the SWR abstraction which is unfortunate because it's such a great abstraction.

@tanmaylaud
Copy link
Contributor

@derindutz , in that case, I don't think it's an issue with SWR. That is how react hooks work in general. You can write the above code with any other hook, and the results will be similar.

@sergiodxa
Copy link
Contributor

This happens because React render once with the first hook updated and then with the second hook updated, this cause this temporarily incorrect value.

@derindutz
Copy link
Author

derindutz commented Jul 21, 2020

Yep that's indeed why it happens, and I think there's a way to avoid it!

Take this example and open up the console: https://codesandbox.io/s/swr-test-9utv8?file=/src/App.js

If you use SWR, you get the temporarily incorrect value.

If you use the window object, there isn't any temporary incorrectness.

Check out this screenshot:
image

I'm not too familiar with the SWR codebase, but it seems like you could do something similar to avoid temporary incorrectness. Whether that's too complicated to be worth it is another question, but it seems possible.

@sergiodxa
Copy link
Contributor

I don't think that is a good pattern, specially because you are polluting the window object, a library at least should avoid polluting it, also note how you are keeping an extra state only to be able to re-render React.

SWR already has a cache, when you mutate data this will be updated in the cache and hooks subscribed to the same cache key (that is what you key is used for) will receive the update and React will render it, but we can't make React render all of them at the same time.

@derindutz
Copy link
Author

derindutz commented Jul 21, 2020

Thank you so much for your prompt response and for taking the time to help.

I agree you wouldn't want to use the window object. I used it as an example, but it works with a cache object too. I've updated it here if you're curious: https://codesandbox.io/s/swr-test-9utv8?file=/src/App.js

I'm a bit confused why this wouldn't work with SWR. Please correct me if I'm wrong, but React renders components, not hooks, so it should be possible to have all hooks with the same key in the same component point to the same value. Then when React renders the component and runs the component function, all useSWR calls with the same key return the same data.

@derindutz
Copy link
Author

derindutz commented Jul 21, 2020

Also, to address your comment regarding misusing state: it seems like swr does something similar under the hood, so it doesn't seem like that would be the issue:

https://github.com/vercel/swr/blob/master/src/use-swr.ts#L217
image

@sengho66
Copy link

sengho66 commented Apr 3, 2022

Bug report

Hi! First, I just wanted to say thank you for your work on this library 😊 It's been a ton of fun to use and has made both my development process and the product I'm working on faster.

Description / Observed Behavior

useSWR calls in the same component with the same key yield different data

Expected Behavior

I'd expect useSWR calls in the same component to yield the same data. I was using helper hooks and two helpers called useSWR with the same key. My code relied on both calls returning the same data. This led to a weird and unexpected bug that took multiple hours to figure out.

Repro Steps / Code Example

https://codesandbox.io/s/swr-test-9jcdz?file=/src/App.js

Additional Context

SWR version: 0.2.3

Thanks for your help!

Hey, do you happen to be calling it from a few places in components? I believe on first load they should yield the same data but not when you change route. Can you confirm?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
help wanted Extra attention is needed
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants