Flickering UI with solidstart
When I am on dark mode with tailwindcss and I navigate between routes for the first time, the theme is for a moment light before going dark. This is very bad for user experience.
issue happens when:
- first load
- reloading page
- navigating between routes for 1st time
60 Replies
component that changes theme (placed in header which is fixed and visible outside routes, directly placed in root.jsx).
and for example about route
@davedbase
Responding to your last comment on the solid-start channel: part of the issue is that localStorage doesn't exist on the server when you first visit the application.
localStorage is a browser API
So you'll have to guard access to it on first load:
It would be better to store the dark mode value in a cookie because then the server would have access to it and could SSR the dark mode property on load.
Ok thanks I am using ssr false so for me everything works good
Yeah. ๐
I'm glad!
but the UI flickering any idea why it is happening ?
On first load?
issue happens when:
- first load
- reloading page
- navigating between routes for 1st time
It's the same issue, the page always starts with a default of not having dark mode.
You just used ssr: false to disable the server-side rendering to fix localStorage.
The proper way to solve this is store the dark mode state in a cookie and SSR the value on load.
the ssr false was already set up before my question. I was referring to stackblitz
but I need also window.etherum
You could enable SSR and check if window exists before accessing that property.
In essence the flicker you're seeing isn't a Start issue itself, it's an issue with being able to properly store the value in a safe place that can be SSRd so that upon initial load the value is already set.
You'll find the flicker is an issue for any SPA (which is what you are basically serving up when you use ssr: false)
you mean a spa with routes ?
Any SPA, really.
well here on one of my sites I did some time ago it doesn't flicker https://rattlessnake.github.io/Factorization-Calculator/ using react
try setting dark mode and reloading
Well, it's actually still happening but the load time is masking it here. If you change your Network tab to Slow 3G throttle you can see the flicker.
The white is the gap between the first paint and the JS being resolved.
yes but the white is on the entire page, I believe this happens frequently on low internet connection. My flickering only happens on the main, not the header (which is directly in root.jsx)
yes absolutely just tried out with my app with low end mobile. So the page is white then content resolves (header + main) but the main is still white for 2 seconds
Sorry, I think we may be on different pages in regards to what the issue is. It would really help if you provided me with a reproduction of your issue so I can support more clearly.
If others have a better understanding please chime in. I might be thinking of this wrong haha
yeah sorry I can't show you my code. But I will give you more info one sec
That's fine, maybe just distill the issue down to the mechanics in a reproduction. Like basically recreate the issue in a simple form via Stackblitz.
header is in root.jsx
topmenu is where you change theme
topmenu
@davedbase I mean that is basically it
Where is TopMenu inserted into the application? Is it composed in Header?
yes index.jsx
of header
root.css if you want
you need to know that a default web page is white until some CSS tells it otherwise createEffect will run once the component is mounted, not before so you have default web page (white) -> component mounts -> effect runs and turns it dark@numnumberry what should I do then ?
ile show you, let me get some code
basically it is implementing what he said here
Here's an example: https://stackblitz.com/edit/github-697vjw?file=src/routes/about.tsx of what you're currently doing right?
so ssr is true now ?
my app gets broken when I enable ssr
errors poping everywhere lol
that may be due to unrelated code you got going on lol
As mentioned because the server doesn't have a
localStorage
object ๐
You have to guard against accessing that with isServer
or checking if it existsyes and how to access window.etherum ?
You cannot from the server
then how ?
you would need to wait until it gets to and runs in the client and call it with createEffect()
please kindly show me on here on to implement this
I dont know the entirety of your code or what you are trying to do
but to stop the CSS flickering the idea is to set the CSS on the server before it ever gets to the client
NOT to set it on the client using createEffect, because by then its slightly too late and you see the white flicker
That should work in SSR. onMount isn't called on the server. Also nothing happens until you click. Are you having issues with this though? If so what specifically?
Also this seems a departure from the original issue hehe
In regards to the dark mode concern, here's an example of my reproduction working as expected....
Does yours not operate that way?
try going dark then reload
Yeah you'll see white then the page will load.
no only main is white...
Likely because createEffect is calling after mount and adding dark to the header. So the sequence of events is:
- Page loads
- JS is loaded page is painted
- Route loads and component is mounted and rendered
- createEffect kicks in after mount and makes dark
ok now ssr works
ok guys thanks I'll fix this tomorrow kinda late here ๐
I'll do the cookie thing
There are some super helpful primitives to make your life easier by the way ๐ https://github.com/solidjs-community/solid-primitives/tree/main/packages/media#useprefersdark
GitHub
solid-primitives/packages/media at main ยท solidjs-community/solid-p...
A library of high-quality primitives that extend SolidJS reactivity. - solid-primitives/packages/media at main ยท solidjs-community/solid-primitives
This is definitely resolvable though. I'm a bit out of time but it would be wonderful if someone could factor an example that used cookies + the above primitive to demonstrate how to solve this with SSR. I'm sure our friend @rattlessnake would really appreciate it!
Hi, just few things before I close this post. Now that I use ssr, is this the correct way to access window?
I have to go through state everytime ?
is it good pratice to use ErrorBoundary ?
you should access window inside a createEffect (or onMount, which is a createEffect under the hood)
I guess you can also access window inside a check for
if (!isServer) {}
I would say its good practice at the top level, it will catch errors you do not catch yourselfshould I wrap errorBoundary only on routes or on entire body ?
I mean when there is an error in routes my entire app still crashes
so what is the point ?
you should wrap it around any components that could throw errors, I dont think you need to worry about <Body /> since this is a solid-provided component
I am not sure about the nature of your errors
@davedbase hi to toggle between dark/light with solid-primitives, do I still add/remove dark class so it works with tailwindcss?
@davedbase The whole issue was just tied to the fact I did not use
Suspense
!!Oh around the router might make sense? You werenโt calling any data though lol
in the root.jsx yes
also do you advise me to switch back to ssr: false ?
Again depends what youโre trying to accomplish ๐
well I mean something like etherscan ?
I donโt known what that is, sorry
Ethereum (ETH) Blockchain Explorer
Ethereum (ETH) Blockchain Explorer
Etherscan allows you to explore and search the Ethereum blockchain for transactions, addresses, tokens, prices and other activities taking place on Ethereum (ETH)
anyways there is no client data stored since it is all done through web3 wallet
so I don't need the server
Yeah sorry crypto and blockchain completely and totally elude me
Although I would like to have some sort of logging system (which logs who connects, ip, etc and store it to text file)
like morgan.js
can I do this with csr