codesandbox/sandpack

SandpackProvider not triggering rerenders when props change on NextJS 13/14

danieldelcore opened this issue · 3 comments

Bug report

Packages affected

  • sandpack-client
  • sandpack-react

Description of the problem

When using the sandpack provider in a Nextjs 13/14 (app directory) context, I found that the theme (and other props) do not trigger a rerender when they change.

Here's the code for a repro but note this is only visible when using nextjs.
https://codesandbox.io/p/sandbox/dank-wood-9gtfp5?file=%2Fsrc%2FApp.tsx%3A23%2C51

I suspect that this has something to do with nextjs' new App dir and RSCs, however it could also be possible that props are being heavily cached inside of sandpack itself.

What were you doing when the problem occurred?

Updated the state of the SandpackProvider via useState in nextjs

What steps can we take to reproduce the problem?

  • npx create-next-app@latest
  • Copy the code from this sandbox into a client component
  • Update the theme via the select box
  • Theme wont be updated

Link to sandbox: link

Your Environment

Software Name/Version
Sandpack-client version na
Sandpack-react version 2.11.3
Browser na
Operating System na

In fact this might be reproducible on the website. I could have sworn this theme switcher updated the color scheme of the editor but now it looks like it does nothing 🤔

image

Ok, it seems to be fixed after downgrading to "@codesandbox/sandpack-react": "2.0.22" 😅

Here's a new repro link with a broken switcher https://codesandbox.io/p/sandbox/dank-wood-9gtfp5?file=%2Fpackage.json%3A8%2C45

Looks like the issue was introduced in 2.11.0, possibly in this PR 🤔 #1050

My guess, we might need to add prefferedTheme to the deps array and update it even if themeFromProps is auto:

https://github.com/codesandbox/sandpack/pull/1050/files#diff-ef320de67c942aac6167958e5b1f652adb01179be4aba48f40651de9cea7c50cR80

  React.useEffect(() => {
-    if (themeFromProps !== "auto") return;
+   if (themeFromProps !== "auto") {
+      setPreferredTheme(setPreferredTheme);
+      return;
+   }

    const colorSchemeChange = ({ matches }: MediaQueryListEvent) => {
      setPreferredTheme(matches ? "dark" : "light");
    };

    window
      .matchMedia("(prefers-color-scheme: dark)")
      .addEventListener("change", colorSchemeChange);

    return () => {
      window
        .matchMedia("(prefers-color-scheme: dark)")
        .removeEventListener("change", colorSchemeChange);
    };
  }, [themeFromProps]);