{"id":12112,"library":"swr","title":"SWR: React Hooks for Data Fetching","description":"SWR is a lightweight and performant React Hooks library for remote data fetching, currently at version 2.4.1. It implements the 'stale-while-revalidate' cache invalidation strategy, popularized by HTTP RFC 5861, to provide an always-fresh and responsive user interface. Maintained by Vercel, SWR ensures components receive a continuous stream of data updates automatically. It offers robust features like built-in caching, request deduplication, real-time revalidation on focus/network recovery, polling, pagination, local mutation for optimistic UI, smart error retry, and comprehensive TypeScript support. Its predictable release cadence, with frequent minor updates and patches, ensures ongoing stability and feature enhancements. Key differentiators include its simplicity with a single `useSWR` hook, strong focus on performance and developer experience, and broad support for modern React features like Suspense.","status":"active","version":"2.4.1","language":"javascript","source_language":"en","source_url":"https://github.com/vercel/swr","tags":["javascript","swr","react","hooks","request","cache","fetch","typescript"],"install":[{"cmd":"npm install swr","lang":"bash","label":"npm"},{"cmd":"yarn add swr","lang":"bash","label":"yarn"},{"cmd":"pnpm add swr","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"SWR is a React Hooks library and requires a compatible version of React to function.","package":"react","optional":false}],"imports":[{"note":"The primary data fetching hook, `useSWR`, is a default export. Attempting to destructure it as a named export will result in an error.","wrong":"import { useSWR } from 'swr'","symbol":"useSWR","correct":"import useSWR from 'swr'"},{"note":"`SWRConfig` is a named export used to provide global configurations to all `useSWR` hooks within its scope. Do not attempt to import it as a default export.","wrong":"import SWRConfig from 'swr'","symbol":"SWRConfig","correct":"import { SWRConfig } from 'swr'"},{"note":"`useSWRImmutable` is a named export, functioning similarly to `useSWR` but for data that should not revalidate. Incorrectly importing it as default will cause issues.","wrong":"import useSWRImmutable from 'swr'","symbol":"useSWRImmutable","correct":"import { useSWRImmutable } from 'swr'"},{"note":"When importing types like `Key`, `Fetcher`, or `SWRResponse`, ensure to use `import type` for better type safety and to prevent accidental runtime imports.","wrong":"import { Key } from 'swr'","symbol":"Key","correct":"import type { Key } from 'swr'"}],"quickstart":{"code":"import useSWR from 'swr';\n\nconst fetcher = async (url) => {\n  const res = await fetch(url);\n  if (!res.ok) {\n    const error = new Error('An error occurred while fetching the data.');\n    error.info = await res.json();\n    error.status = res.status;\n    throw error;\n  }\n  return res.json();\n};\n\nfunction UserProfile() {\n  // In a real application, you might use an environment variable for the base URL\n  const API_BASE_URL = process.env.NEXT_PUBLIC_API_URL ?? 'https://api.example.com';\n  const userId = '123'; // Example user ID\n  const { data, error, isLoading } = useSWR(`${API_BASE_URL}/users/${userId}`, fetcher);\n\n  if (error) return <div>Failed to load user data: {error.message}</div>;\n  if (isLoading) return <div>Loading user profile...</div>;\n  \n  return (\n    <div>\n      <h1>User Profile</h1>\n      <p>Name: {data.name}</p>\n      <p>Email: {data.email}</p>\n    </div>\n  );\n}\n\n// Example of how to render it (e.g., in a React component tree)\n// function App() {\n//   return <UserProfile />;\n// }\n// export default App;","lang":"typescript","description":"Demonstrates basic data fetching using `useSWR` with a custom `fetcher` function, handling loading and error states for a user profile."},"warnings":[{"fix":"Review the SWR v2 migration guide on the official documentation. Update `isValidating` to `isLoading` for initial load checks. Adjust `mutate` calls to `mutate(key, data, { revalidate: false })` for preventing revalidation.","message":"SWR v2 introduced breaking changes related to the return shape of the `useSWR` hook, error handling, and `mutate` API. Specifically, `isValidating` was replaced with `isLoading` for initial data fetching state, and the `mutate` function no longer accepts `shouldRevalidate` as a direct boolean argument but as part of an options object.","severity":"breaking","affected_versions":">=2.0.0"},{"fix":"Ensure your project is configured to handle ESM imports, especially for bundlers like Webpack or Rollup. For Node.js, ensure `\"type\": \"module\"` in `package.json` or use `.mjs` extensions. If strictly using CommonJS, explicit `require('swr/dist/index.cjs')` might be necessary, though not officially recommended.","message":"SWR transitioned to an ESM-first package distribution starting from v2. While CJS bundles are still provided for backward compatibility, ESM is the recommended way to import. Users with older tooling or specific CommonJS setups might face issues.","severity":"breaking","affected_versions":">=2.0.0"},{"fix":"Ensure `useSWRImmutable` explicitly overrides any global `refreshInterval` via its options: `useSWRImmutable(key, fetcher, { refreshInterval: 0 })`. Version 2.4.0 and later should correctly handle this override, but explicit setting provides clarity and robustness.","message":"When using `useSWRImmutable`, global `refreshInterval` settings might still trigger revalidations. This can lead to unexpected data refreshes for data intended to be static.","severity":"gotcha","affected_versions":">=2.4.0"},{"fix":"Immediately upgrade SWR to version 2.3.8 or newer to patch these critical security vulnerabilities. Review any potentially affected deployments for signs of compromise.","message":"Multiple critical RCE (Remote Code Execution) vulnerabilities (CVE-2025-55182, CVE-2025-55183, CVE-2025-55184) were identified and patched in version 2.3.8. These vulnerabilities could allow an attacker to execute arbitrary code.","severity":"breaking","affected_versions":"<2.3.8"},{"fix":"Always wrap components using `useSWR` with `suspense: true` in a `<Suspense>` boundary. Remove `if (isLoading)` or `if (!data)` checks as they are not needed; the component will only render once data is available. Handle errors using `error` boundary components.","message":"When `useSWR` is enabled in Suspense mode (`suspense: true`), the `data` property will never be `undefined` (it will throw a Promise instead). Components must be wrapped in `<Suspense>` boundary. Misunderstanding this can lead to 'cannot read properties of undefined' errors.","severity":"gotcha","affected_versions":">=1.0.0"}],"env_vars":null,"last_verified":"2026-04-19T00:00:00.000Z","next_check":"2026-07-18T00:00:00.000Z","problems":[{"fix":"Change your import statement from `import { useSWR } from 'swr'` to `import useSWR from 'swr'`.","cause":"Attempting to import `useSWR` as a named export when it is a default export.","error":"Error: useSWR is not a function"},{"fix":"Always check for `isLoading` or `error` before accessing `data`. Example: `if (isLoading) return <div>loading...</div>; if (error) return <div>failed to load</div>; return <div>hello {data.name}!</div>`.","cause":"Attempting to access `data` before it's loaded, especially when not using Suspense, or when `data` is `undefined` due to an error or initial loading state.","error":"TypeError: Cannot read properties of undefined (reading 'name') at Profile"},{"fix":"Ensure your project uses `import` statements for SWR. If using Node.js, confirm `\"type\": \"module\"` is set in your `package.json` or use `.mjs` extensions for files importing SWR. Check bundler configuration (e.g., Webpack, Rollup) to correctly resolve ESM modules.","cause":"Mixing CommonJS `require()` with an ESM-first library like SWR, or incorrect bundler configuration for ESM modules.","error":"Failed to compile. Module parse failed: Cannot assign to read only property 'exports' of object '#<Object>'"},{"fix":"Configure TypeScript by ensuring `\"compilerOptions\": { \"exactOptionalPropertyTypes\": true }` is not set to `false` if it conflicts. More practically, if `suspense: true` is used, TypeScript should infer `data` as non-nullable. If it doesn't, ensure your TypeScript version is compatible and explicitly assert type if necessary (e.g., `data!.name`), though this should ideally be avoided.","cause":"When `suspense: true` is enabled, SWR guarantees `data` will always be defined at the component render point, but TypeScript might still infer it as `data | undefined` without proper configuration.","error":"Type 'undefined' is not assignable to type '...' when using data from useSWR with TypeScript and Suspense is enabled."}],"ecosystem":"npm"}