0

I am trying to add a splash screen before React loads.

since i am using react scripts / react-app my index.tsx only has this part:

ReactDOM.render(<App />, document.getElementById("root"));

i tried adding my own div on the same page but it doesn't show.

i would like to display a simple blank screen with my splash image on a 1 second timer before react loads to avoid/hide the shifting of the rendering elements.

** if i do add the screen in app.tsx, the shifting happens before the screen loads

update

as Rishabh pointed out below, index.html is in /public folder. So I ended up combining 2 approaches.

  1. add a screen before react starts:

    <div id="root">
      <div id="dimScreen">
        <img src="/img/logo.png" />
      </div>
    </div>
    
  2. 2.

loading a proper loader non top for .5 - 1 sec

class App extends Component {
    state = {
        loading: true
    }
    componentDidMount() {
        setTimeout(() => {
            this.setState({ loading: false });
        }, 1000);
    }
    render() {
        return (
            <React.Fragment>
                {
                    this.state.loading ?
                        <Loader />
                        : (
                            <div className="app">
                                <Header />
                                <MyComponent />
                            </div>
                        )
                }
            </React.Fragment>
        );
    }
}

so far this approach is working best but will update if i find issues or something better

Sonic Soul
  • 23,855
  • 37
  • 130
  • 196
  • What do you mean by shifting? Why don't you have something like isLoading variable in the state and conditionally render your the app? Like if it is loading then display null or a splash screen and once you have all the stuff ready display the full App? – Hamed Mar 19 '19 at 15:18
  • The snippet in the second solution in this post might also help: https://stackoverflow.com/a/40989121/9598077 – Hamed Mar 19 '19 at 15:23

3 Answers3

2

So just go to your index.html inside your public folder and inside

<div id="root"><-- Add Splash screen html code here --></div>

add your splash screen code, when react loads it replaces all the content inside the div with id root

Rishabh Rawat
  • 849
  • 6
  • 11
  • there is no index.html. this is a react app that generates index.tsx. i already tried adding my splash page there as indicated in my question – Sonic Soul Mar 19 '19 at 15:31
  • 1
    Worth mentioning - if you are building a PWA and want to have an image inside index.html `
    ` use SVG or convert your image to base64 and use a data URI. This ensures that the image ends up in the auto-generated pre-cache manifest, as the data is directly embedded into index.html, rather than in a separate image file.
    – cnanders Oct 20 '19 at 23:45
1

This is an example to show loader for five seconds using state and setTimeout(), In place of <Loader/> you can give splash screen component.

import React, { Component } from 'react';

import Drawer from '../Drawer/Drawer';
import Loader from '../../components/UI/Spinner/Loader/Loader';

class App extends Component {
  state = {
    loading: true
  }

  componentDidMount(){
    setTimeout(() => {
      this.setState({loading: false});
    }, 5000);
  }

  render() {  
    return (
      <React.Fragment>
        {
          this.state.loading ? <Loader />: <Drawer />
        }
      </React.Fragment>
    );
  }
}

export default App;

i hope it helps!

Engineer
  • 1,243
  • 11
  • 18
0

I'm not sure if this will work at all, it's not tested but maybe it'll lead you to the right direction? So, here's my 2 cents

withSplash.js

const withSplash = MyAppComponent => 
  class extends React.Component {
    state = {
      showSplash: true
    }

    componentDidMount () {
      handleSplashComponent(); 
    }

    componentWillUnmount () {
      if (this.timer) {
        this.timer = null;
      }
    }

    handleSplashComponent = () => {
      this.timer = setTimeout(()=> {
        this.setState({
          showSplash: false
        })
      }, 3000)
    }

    render () {
      return this.state.showSplash
        ? <SplashComponent />
        : <MyAppComponent />
    }
  }

App.js

class App extends Component {
  ...
}

export default withSplash(App);

AnotherComponent.js

class AnotherComponent extends Component {
  ...
}

export default withSplash(AnotherComponent);
Shawn Yap
  • 969
  • 7
  • 12
  • thanks! i tried this route but by the time react code executes its too late. i needed something more immediate. the solution in index.html works very well – Sonic Soul Mar 19 '19 at 15:43
  • actually the index.html solution is still jerky :( i will try your approach now – Sonic Soul Mar 19 '19 at 15:51
  • hey hey have not tried specifically yet as the other was similar and it worked, but looks like it would work the same! – Sonic Soul Mar 20 '19 at 18:21