What worked in getting data to my first render was initializing the redux store like so:
if (typeof localStorage != "undefined") {
initialState = {
theme: localStorage.getItem("theme"),
};
} else {
initialState = {};
}
const store = createStore(reducers, initialState);
But it worsened the situation as the components no longer re-rendered on first load because the theme
prop from redux never changed because the store was initialized with the user preference. So I went back to the old approach with in the original question above.
The flicker happens because I am using Javascript to control the theme in my react app. I am also using Gatsby which generates a static version of my site that loads before my react app.
Loading the site goes like this:
E.g. User with dark theme preference visits. They see static content without any Javascript while JS bundles download in the background.
Since light theme is the default, the static version of the site will be light.
Javascript loads and React's first render happens and the redux store is intialized. The root component gets the theme from localStorage
and the tree re-renders with the dark theme.
The flicker happens because of the events between 2 and 3.
I didn't manage to solve the issue completely. But I managed to alleviate the flicker to be much more unnoticable by enabling Gatsby's service worker. The worker caches Javascript bundles for next site visit, and loading Javascript from disk means the flicker will linger for a shorter amount of time as the JS bundles are already available for execution.