Global variants not respected after reload.

We ran into a bit of an issue with global variants, and I’m not sure this is something that I have to fix in our code
We have a switch that changes the Mode between light and dark mode (dark is the default, both in code and in plasmic) and if the end-user changes it, it persists to local storage.
This part is working as expected.
This value is provided to the PlasmicRootProvider like this:

<PlasmicRootProvider
  // ...
  globalVariants={[{name: "Mode", value: isDarkMode ? 'dark' : 'light'}]}
>
  <PlasmicComponent component={pageMeta.displayName} />
</PlasmicRootProvider>

Checking with React Developer Tools I found this component and it seems it always gets the proper values.
Despite this, if the user preference is light the components do not respect them after a reload.
(It works as expected when clicking on the toggle switch.)

Can I get some help with this?

Some computers/phones might show the correct mode in those cases it just flickers.
(as expected as far as I can tell reading the chat history).

Can you share anything to your plasmic project as well as a link to the live published page where it isn’t working?

And so we can try it out he also let me know where on the page to look for the toggle, and where it isn’t rendering correctly

@yang Just DM’d you with the requested details.

@yang Hi! I wanted to follow up on this, both @conservation_sheep , @fiscal_mastodon and I are looking for feedback. Thank you!

The issue is with server-side/static pre-rendering of the HTML - it’s always going to be rendering the default variant on the server where it doesn’t know what is the state.

On the client, React simply accepts whatever the server sent as the DOM it needs to hydrate (doesn’t make any changes to the DOM).

One solution is to rerender the correct variant a second time on the client (when it does know the state), via a useEffect(). Note this will result in an initial flash of the wrong theme.

If you’re using getServerSideProps (SSR), you could also find a way to communicate with the server what the stored preference is of the user (e.g. by persisting via cookies), and have the server pre-render the appropriate variant.

I see, we are currently using SSG (getStaticProps), since it is build time, I think the cookie solution won’t work.
(But we might be able to change that, I’ll check.)

Currently, we are using useLocalStorage from usehooks-ts to handle the persistence of the isDarkMode global variable.
(This basically persists the useState variable to localstorage when it changes, it has a default value just like useState has, but it is only used if the user has no value in the local storage for the darkmode)
const [isDarkMode] = useLocalStorage('veezla-darkmode', true);
I’m not sure, how does the useEffect would look like?
What should it depend on and what should it do?

Since useLocalStorage is basically a useState it should be enough for the render trigger, am I missing something.

Something like this

const [isDarkMode, setIsDarkMode] = useState(false);
useEffect(() => setIsDarkMode(() => localStorage['veezla-darkmode'] ?? false));
<PlasmicRootProvider
  // ...
  globalVariants={[{name: "Mode", value: isDarkMode ? 'dark' : 'light'}]}
>
  <PlasmicComponent component={pageMeta.displayName} />
</PlasmicRootProvider>