Showing a popup after 3 seconds from page load in GatsbyJS (ReactJS) using the hook useEffect()

Viewed 1438

I have a Gatsby JS based website and I am trying to achieve the loading of a modal/popup after 3 seconds after the index page has loaded.

Here is my code so far:

index.js

const HomePage = ({ data }) => {

  const { t } = useTranslation();

  useEffect(() => {
    setTimeout(() => <Modal
    component={<FormA />}
   />, 3000);

  }, []);

  return (

     <Layout>
       ...
     </Layout>
  )
}

modal.js

const Modal = (props) => {

return (

    <div className='modal'>
        <div className="modal-background"></div>
        <div className="modal-content">{props.component}</div>
    </div>

  )
}

export default Modal

No error is detected, but the modal does not show up.

Any clue? Thank you.

2 Answers

Modal does not show up because you are not returning it inside JSX from your component. Returning Modal from the callback function of setTimeout is useless.

To achieve the desired result, create a state in your component that is initially set to false.

const [showModal, setShowModal] = useState(false);

Then inside the useEffect hook, set it to true after three seconds.

useEffect(() => {
    setTimeout(() => showModal(true), 3000);
}, []);

Now to show the modal, conditionally render it in your component's JSX.

return (
   <Layout>
     { showModal ? <Modal/> : null }
     ...
   </Layout>
)

We can use a local state variable, which will be initially false and after component mounts we will make that variable true and we will clear the timeout when component unmounts.

function HomePage() {
  const [showModal, setShowModal] = useState(false)

  useEffect(() => {
    const timeId = setTimeout(() => setShowModal(true), 3000)

    return () => clearTimeout(timeId)
  })

  return (
     <Layout>
        {showModal && <Modal />}
     </Layout>
  )
}

One suggestion which you can do is, make your Modal component take a prop like showModal which will return null, when showModal will be false.

 function Modal({ showModal }) {
  if(!showModal) {
    return null
  }
  return (
    <div>Your Modal</div>
  )
}

and you can use it like this:-

  function HomePage() {
      const [showModal, setShowModal] = useState(false)
    
      useEffect(() => {
        const timeId = setTimeout(() => setShowModal(true), 3000)
    
        return () => clearTimeout(timeId)
      })
    
      return (
         <Layout>
            <Modal showModal={showModal} />
         </Layout>
      )
    }
Related