dom ready event in React
Asked Answered
C

2

16

I have some components like below:

Wrapper: wrap Loader and Page

Loader: some animation

Page: page content

code like this:

<body>
  <div id="app"></div>
</body>

class Loader extends Component {}

class Page extends Component {}

class Wrapper extends Component {
    render() {
        return (
            <Loader/>
            <Page />
        );
    }
}

ReactDOM.render(<Wrapper />, document.getElementById('app'));

I want hide Loader and show Page component after DOM has compeletely loaded.

How should I write dom ready event in React?

like jQuery: $(window).on('ready')

Cranage answered 29/7, 2016 at 4:3 Comment(0)
C
18

TL;DR If I understand correctly, the answer is probably "not possible". But there is another solution...

Here's what I think you're trying to do, described as a series of steps:

  1. page starts loading, <Loader /> component shows a "page loading" animation

  2. page finishes loading, <Loader /> component is removed (or hidden) and <Page /> component is inserted (or shown) with the "real" page content.

Here's the problem: remember that you inject your React components into the page like this:

ReactDOM.render(<Wrapper />, document.getElementById('app'));

You can't actually inject a React component until the DOM is loaded. So by that time, either <Loader /> appears for about 2 milliseconds and disappears, or it doesn't appear at all (since the DOM is already loaded by the time it gets injected into the page).

If you're trying to show a throbber or other simple animation (like an animated GIF), I'd try a hybrid approach:

Set up your HTML like this:

<body>
    <div id="app"><img src="throbber.gif" /></div>
</body>

In your script tag, include a JQuery "document ready" event handler to load the React component:

class Page extends Component {}

class Wrapper extends Component {
    render() {
        return (
            <Page />
        );
    }
}

$(document).ready(function () {
    ReactDOM.render(<Wrapper />, document.getElementById('app'));
});

Notice that I've left out the <Loader /> - the throbber image is doing the work of the loader.

The idea here is that while the page is loading, the throbber GIF will be throbbing away until the DOM is loaded, at which point JQuery's document ready event will fire & the contents of the div#app will be replaced.

I haven't tried this, but it should work, provided that React actually replaces the content of div#app, rather than just appending stuff to it. If that's not the case, then it's a simple matter of changing the document ready handler to something like this:

$(document).ready(function () {
    $('div#app img').remove();
    ReactDOM.render(<Wrapper />, document.getElementById('app'));
});
Cracker answered 29/7, 2016 at 4:35 Comment(3)
This works, React will replace the contents of its mount point. It's important that any CSS the loader depends on are available before React mounts though, so an inline <style> block with just enough CSS for that initial render might be in order.Littoral
No need for Jquery as you can use document.addEventListener("DOMContentLoaded", function(event) { }Teriann
You should use React Suspense and React Lazy now, the result will be much better.Pacifist
T
5

The approach I ended up using (No JQuery needed) is the following:

In the index.html, put the loader element right after the root div

<div id="root">
</div>
<div id="preloader" class="pre-loader">
  <img src="..."> </img>
</div>

Then inside your index.js :

document.addEventListener("DOMContentLoaded", function(event) { 
  
  ReactDOM.render(
    <React.StrictMode>
      <Provider store={store}>
    <BrowserRouter>
      <DashApp />
    </BrowserRouter>
    </Provider>
    </React.StrictMode>,
    document.getElementById("root")
  );

  const loadingScreen = document.getElementById("preloader");
   loadingScreen.style.opacity = 0;
   loadingScreen.style.display = "none";
});

So basically we simply follow a similar approach to what the other answer suggests, but without the need of JQuery cause we listen to the loading event using

document.addEventListener("DOMContentLoaded", function(event) { }

Another approach would be just placing the loader inside the root div which means React will overwrite it by default when it loads:

<div id="root">
  <div id="preloader" class="pre-loader">
    <img src="..."> </img>
  </div>
</div>
   

My personal full approach can be seen in this

Teriann answered 20/11, 2020 at 23:59 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.