This is an example from Google Adsense application page. The loading screen displayed before the main page showed after.
I don't know how to do the same thing with React because if I make loading screen rendered by React component, it doesn't display while page is loading because it has to wait for DOM rendered before.
Updated:
I made an example of my approach by putting screen loader in index.html
and remove it in React componentDidMount()
lifecycle method.
Example: https://nguyenbathanh.github.io
Source: https://github.com/nguyenbathanh/react-loading-screen
Setting the timeout in componentDidMount works but in my application I received a memory leak warning. Try something like this.
Since you render react into a DOM container -
<div id="app"></div>
, you can add a spinner to that container, and when react will load and render, the spinner will disappear.The problem:
React will replace the contents of the container as soon as
ReactDOM.render()
is called. Even if you rendernull
, the content would still be replaced by a comment -<!-- react-empty: 1 -->
. This means that if you want to display the loader while react renders, a loader markup placed inside the container (<div id="app"><div class="loader"></div></div>
for example) would not work.Solution:
My solution is to add the loader class directly to the container, but with the
:empty
pseudo class. The spinner will be visible, as long as nothing is rendered into the container (comments don't count). As soon as react renders an element, the loader will disappear.In the example you can see a component that renders
null
until it's ready. The container is the loader as well -<div id="app" class="app"></div>
, and the loader's class will only work if it's:empty
(see comments in code):A variation on using the
:empty
pseudo class to/show hide selector, is setting the spinner as a sibling element to the app container, and showing it as long as the container is empty using the adjacent sibling combinator (+
):The workaround for this is:
In your render function do something like this:
Initialize isLoading as true in the constructor and false on componentDidMount
I'm also using React in my app. For requests I'm using axios interceptors, so great way to make loader screen (fullpage as you showed an example) is to add class or id to for example body inside interceptors (here code from official documentation with some custom code):
And then just implement in CSS your loader with pseudo-elements (or add class or id to different element, not body as you like) - you can set color of background to opaque or transparent, etc... Example:
I had to deal with that problem recently and came up with a solution, which works just fine for me. However, I've tried @Ori Drori solution above and unfortunately it didn't work just right (had some delays + I don't like the usage of
setTimeout
function there).This is what I came up with:
index.html
fileInside
head
tag - styles for the indicator:Now the
body
tag:And then comes a very simple logic, inside
app.js
file (in the render function):How does it work?
When the first component (in my app it's
app.js
aswell in most cases) mounts correctly, thespinner
is being hidden with applyinghidden
attribute to it.What's more important to add -
!spinner.hasAttribute('hidden')
condition prevents to addhidden
attribute to the spinner with every component mount, so actually it will be added only one time, when whole app loads.If anyone looking for a drop-in, zero-config and zero-dependencies library for the above use-case, try pace.js (http://github.hubspot.com/pace/docs/welcome/).
It automatically hooks to events (ajax, readyState, history pushstate, js event loop etc) and show a customizable loader.
Worked well with our react/relay projects (handles navigation changes using react-router, relay requests) (Not affliated; had used pace.js for our projects and it worked great)