Home > Enterprise >  Display two React components one after another
Display two React components one after another

Time:04-11

I have a quiz game where you have to remember the items(from images) and answer the quiz. First,4 images are shown with the time interval of 2 secs and after that the 4 quiz will start. I have Images component(which display images in intervals) and Quiz component. I want to hide the images component once it is finished and show the quiz. I tried to do it using conditional rendering but its not working.

import { useState, useEffect } from "react";

import Quiz from "./Quiz.js";
import Images from "./Images";
import "./styles.css";

const images = [
  "https://picsum.photos/id/1/200/300",
  "https://picsum.photos/id/2/200/300",
  "https://picsum.photos/id/3/200/300",
  "https://picsum.photos/id/4/200/300"
];

export default function App() {
  const [image, setImage] = useState();
  const [showImages, setShowImages] = useState(true);
  const [showQuestions, setShowQuestions] = useState(false);

  useEffect(() => {
    const function1 = () =>
      images.forEach((c, i) => setTimeout(() => setImage(c), i * 2000));

    function1();
    //setShowImages(false);
  }, []);

  return (
    <div className="App">
      <div className="screen">
        {showImages && <Images image={image} />}
        {showQuestions && <Quiz />}
      </div>
    </div>
  );
}

codesanbox link: https://codesandbox.io/s/elastic-snowflake-qo1nz7?file=/src/App.js

CodePudding user response:

I hope this will solve your problem.

  useEffect(() => {
    setShowQuestions(false);
    setShowImages(true);
    const function1 = () =>
      images.forEach((c, i) => setTimeout(() => setImage(c), i * 2000));

    function1();
    setTimeout(() => {
      setShowImages(false);
      setShowQuestions(true);
    }, images.length * 2000);
  }, [])

Here's a codesandbox link https://codesandbox.io/s/wizardly-elion-4dh35s?file=/src/App.js

CodePudding user response:

for a quick solution, you can do like that https://codesandbox.io/s/romantic-paper-bzknn8

 useEffect(() => {
    const function1 = () =>
      images.forEach((c, i) =>
        setTimeout(() => {
          setImage(c);
          if (i == 3) {
            setShowImages(false);
            setShowQuestions(true);
          }
        }, i * 2000)
      );

    function1();
    //setShowImages(false);
  }, []);

CodePudding user response:

Try This!

  useEffect(() => {
    const function1 = () => {
      let timer = 0;
      images.forEach((c, i) => {
        timer  ;
        setTimeout(() => setImage(c), i * 2000);
      });
      setTimeout(() => {
        setShowImages(false);
        setShowQuestions(true);
      }, timer * 2000);
    };
    function1();
  }, []);

CodePudding user response:

One simple way is to keep the showQuestions logic once the last image is loaded.

 const function1 = () =>
  images.forEach((c, i) => {
    setTimeout(() => {
      setImage(c)
      if(i == images.length - 1) {
        setTimeout(() => {
          setShowImages(false);
          setShowQuestions(true); 
        }, 1000)
      }
    }, i * 2000)
  });

You can also try simple wrapper logic with promise.

useEffect(() => {
const function1 = () =>
  new Promise(res => {
    images.forEach((c, i) => setTimeout(() => {
      setImage(c);
      if(i === images.length - 1) {
        res();
      }
    }, i * 2000));
  });

function1().then(() => {
  setTimeout(() => {
    setShowImages(false);
    setShowQuestions(true)
  }, 2000)
});
}, []);
  • Related