vercel / swr-site

The official website for SWR.
https://swr.vercel.app
Apache License 2.0
485 stars 353 forks source link

Error occurs when Usage with Next.js and Cache are combined #574

Closed yuya-tani closed 6 months ago

yuya-tani commented 6 months ago

Hey. I would like to use "persistent cache using LocalStorage" in the URL below with Next.js v14 SSG. https://swr.vercel.app/ja/docs/advanced/cache#localstorage-based-persistent-cache

I created "SWRConfig" as a client component as shown below, but even if I use use client, I get an error "localStorage is not defined" when I build it. https://swr.vercel.app/ja/docs/with-nextjs#client-components

Trying to get around it, use "typeof window !== 'undefined'" If you do it while there is a window object (client), as in "Hydration failed because the initial UI does not match what was rendered on the server." I got a hydration error.

Is there a way to avoid both?

localStorage is not defined ERROR

"use client";

import { SWRConfig } from "swr";

const localStorageProvider = () => {
  const map = new Map(JSON.parse(localStorage.getItem("dinet-app-cache") || "[]"));
  window.addEventListener("beforeunload", () => {
    const appCache = JSON.stringify(Array.from(map.entries()));
    localStorage.setItem("app-cache", appCache);
  });
  return map;
};

const config = {
  refreshInterval: 300000,
  provider: localStorageProvider,
};

export const SWRProvider = ({ children }) => {
  return (
    <SWRConfig value={config} suppressHydrationWarning>
      {children}
    </SWRConfig>
  );
};

Hydration ERROR

"use client";

import { SWRConfig } from "swr";

const localStorageProvider = () => {
  if (typeof window === "undefined") {
    return new Map([]);
  }
  const map = new Map(JSON.parse(localStorage.getItem("dinet-app-cache") || "[]"));
  window.addEventListener("beforeunload", () => {
    const appCache = JSON.stringify(Array.from(map.entries()));
    localStorage.setItem("app-cache", appCache);
  });
  return map;
};

const config = {
  refreshInterval: 300000,
  provider: localStorageProvider,
};

export const SWRProvider = ({ children }) => {
  return (
    <SWRConfig value={config} suppressHydrationWarning>
      {children}
    </SWRConfig>
  );
};
yuya-tani commented 6 months ago

I found the following answer from the swr issue. https://github.com/vercel/swr/issues/2125#issuecomment-1504812584

We have confirmed that there are no errors using this setting method. I should have looked at the swr issue first instead of swr-site. sorry.

I would be happy if the above example was also included in the sample site. Best regard.