conditional rendering with useEffect() and setTimeOut()

Viewed 4521

I've got two components in my react application. one of them is for the initial loading that will show some loading animations, and I want this one to render for about three seconds, and the other component is just a counter that I want to render after the first one. how can I do this with useEffect() and setTimeOut()? (or with any other methods)

function App() {
  return(
     <>
       <Loading />
       <Counter />
     </>
  )
}
4 Answers

Here you go :

This is just a code snippet showing useEffect and setTimeout, in your case you can use real component instead of string in below.

Just run the snippet and hope it will clear your thoughts :

const { useState , useEffect } = React;

const App = () => {

  const [loading,setLoading] = useState(true);

  useEffect(() => {
    setTimeout(() => {
      setLoading(false);
    },3000);
  },[]);

  return (
    <div>
      { loading ? "Loading Component (will be gone in 3 secs)...." : "Counter Component"}
    </div>
  );
}

ReactDOM.render(<App />, document.getElementById('react-root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="react-root"></div>

If you use setInterval(), below would be fine

const App = () => {
  const [loading, setLoading] = React.useState(true);
  React.useEffect(() => {
    const interval = setInterval(() => {
      setLoading(false);
    }, 3000);
    return () => clearInterval(interval);
  }, []);
  return (
    <div className="App">{loading ? <h1>Loading</h1> : <h2>Counter</h2>}</div>
  );
}
ReactDOM.render(<App />, document.getElementById("root"));
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.12.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.12.0/umd/react-dom.production.min.js"></script>

You can set a state prop that is a boolean that let's you render conditionally the counter. So for example

this.state = {
    isCounterVisible: false
}

then you should define a function that starts a timeout with the delay you need, for example

makeCounterVisible() {
    setTimeout(() => {
        this.setState({isCounterVisible: true})
   }, 3000)
}

Then, you call this method from the useEffect hook and remember to pass an empty array as second paramether so that it only runs once

useEffect(() => {
  this.makeCounterVisible();
}, []);

Finally, you add the render condition, like this

  return(this.state.isCounterVisible ? <Counter /> : <Loading />)

You can create a component state which will first render the Loading component for 3 sec and then Counter component. Something like this

const Demo = () => {
  const [showLoader, setLoader] = useState(true);

  useEffect(() => {
    setTimeout(() => {
      setLoader(false);
    }, 3000);
  }, []);

  if (showLoader) {
    return <Loading />;
  }

  return <Counter />;
};

Live demo here: https://codesandbox.io/s/react-example-fo3ju?file=/index.js:179-416

Related