Share requests and listeners

Same-key components share one request, one cache, one listener.

SWRswr.vercel.app
SWR enables request deduplication, caching, and revalidation across component instances.
SWR docsRead docs ↗

From vercel-react-best-practices: client-swr-dedup, client-event-listeners and 1 more.

Ten lists, one request

Drag Instances, press Remount, then change the key.

Fetch per instanceBad
    useEffect(() => { fetch(url)… }, [url])
    useSWR(key, fetcher)Good
      useSWR(url, fetcher)
      function UserList() {
        const { data: users } = useSWR('/api/users', fetcher)
      }

      Many shortcuts, one listener

      Add shortcuts, then press their letters or tap a cap.

      A listener per hookBad
      window0 keydown listeners
      useEffect(() => addEventListener('keydown', h))0 ran
      useSWRSubscriptionGood
      window0 keydown listener

      useSWRSubscription('global-keydown', …)0 ran
      const keyCallbacks = new Map<string, Set<() => void>>()
      
      useSWRSubscription('global-keydown', () => {
        const handler = (e: KeyboardEvent) =>
          keyCallbacks.get(e.key)?.forEach((cb) => cb())
        window.addEventListener('keydown', handler)
        return () => window.removeEventListener('keydown', handler)
      })

      Passive listeners scroll free

      Scroll both boxes, then switch to Custom zoom.

      { passive: false }Bad
      addEventListener('wheel', h)
      { passive: true }Good
      addEventListener('wheel', h, { passive: true })
      el.addEventListener('wheel', track, { passive: true })
      el.addEventListener('wheel', zoom, { passive: false })

      Why it matters, pros and cons

      Why it matters

      Hooks run per instance, so N fetches and listeners. Non-passive ones stall scroll.

      Pros

      • One request per key, any reader count.
      • One listener; shortcuts are Map entries.
      • Passive listeners let the compositor scroll.

      Cons

      • SWR adds a dependency and stale-by-default semantics.
      • Server Component data needs no client cache.
      • Custom zoom or swipe must stay non-passive.