prazdevs / pinia-plugin-persistedstate

💾 Configurable persistence and rehydration of Pinia stores.
https://prazdevs.github.io/pinia-plugin-persistedstate/
MIT License
2.05k stars 118 forks source link

Store not hydrated from cookies when used with `@nuxtjs/i18n` and `routeRules` #293

Open rudolfbyker opened 6 months ago

rudolfbyker commented 6 months ago

Describe the bug

In some very specific circumstances, stores are not hydrated from the cookies.

This is a very esoteric issue. It took me many many hours to finally get a minimal reproduction, and even then I don't understand completely what is happening. See the stackblitz link below for the code. Here is a screen capture video where I walk through the problem: https://github.com/prazdevs/pinia-plugin-persistedstate/assets/10025342/c6651243-f3fc-40a9-aafd-1762d6a8453c

In the reproduction, if you do any one of the following, the problem disappears, and the store is properly hydrated:

I tried to debug this by stepping through the generated code in .output/server/. Much of the code there I don't fully understand (being a user of Nuxt3 rather than a core developer), but here is what I could gather:

In .output/server/node_modules/pinia-plugin-persistedstate/dist/index.mjs we have:

function hydrateStore(store, { storage, serializer, key, debug }) {
  try {
    const fromStorage = storage == null ? void 0 : storage.getItem(key);
    if (fromStorage)
      store.$patch(serializer == null ? void 0 : serializer.deserialize(fromStorage));
  } catch (e) {
    if (debug)
      console.error("[pinia-plugin-persistedstate]", e);
  }
}

storage.getItem() is a call to the getItem method in usePersistedstateCookies() which is seen in .output/server/chunks/build/server.mjs:

function usePersistedstateCookies(cookieOptions) {
  return {
    getItem: (key) => {
      return useCookie(key, {
        ...cookieOptions,
        encode: encodeURIComponent,
        decode: decodeURIComponent
      }).value;
    },
    setItem: (key, value) => {
      useCookie(key, {
        ...cookieOptions,
        encode: encodeURIComponent,
        decode: decodeURIComponent
      }).value = value;
    }
  };
}

Stepping into useCookie(), we find:

function useCookie(name, _opts) {
  var _a;
  const opts = { ...CookieDefaults, ..._opts };
  const cookies = readRawCookies(opts) || {};
  // ...
  return cookie;
}

Stepping into readRawCookies(), we find:

function readRawCookies(opts = {}) {
  {
    return parse$1(getRequestHeader(useRequestEvent(), "cookie") || "", opts);
  }
}

At this point, I put in some console.log statements to see what is going on:

function readRawCookies(opts = {}) {
  {
    const event = useRequestEvent();
    console.log({
      headers: event.node.req.headers,
      rawHeaders: event.node.req.rawHeaders,
    });
    const header = getRequestHeader(event, "cookie");
    console.log(header);
    const result = parse$1(header || "", opts);
    console.log(result);
    return result;
  }
}

If we do this, then we see the following:

Reproduction

https://stackblitz.com/edit/github-5b43sb-okx9lc

System Info

Stackblitz

Used Package Manager

npm

Validations

prazdevs commented 3 weeks ago

could you try that again with v4?