#app
View Compiled
* {
  box-sizing: border-box;
}
:root {
  --control: #e69119;
  --color: #fff;
}
button {
  background: var(--control);
  color: var(--color);
  padding: 1rem 2rem;
  border-radius: 1rem;
  border: 4px solid var(--color);
  font-family: 'Fredoka One', cursive;
  font-size: 1.2rem;
}
body {
  background: linear-gradient(#d1e9fa 0 40%, #86c270 40%);
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: 'Fredoka One', cursive;
}
import React, { Fragment, useEffect, useRef, useState } from 'https://cdn.skypack.dev/react'
import { render } from 'https://cdn.skypack.dev/react-dom'

const Moles = ({ children }) => <div>{children}</div>
const Mole = () => <button>Mole</button>
const Score = () => <div>Score: 0</div>

const TIME_LIMIT = 30000

const Timer = ({ time, interval = 1000, onEnd }) => {
  const [internalTime, setInternalTime] = useState(time)
  const timerRef = useRef(time)  
  const timeRef = useRef(time)
  useEffect(() => {
    timerRef.current = setInterval(
      () => setInternalTime((timeRef.current -= interval)),
      interval
    )
    return () => {
      clearInterval(timerRef.current)
    }
  }, [interval])
  return <div>{`Time: ${internalTime / 1000}s`}</div>
}

const Game = () => {
  const [playing, setPlaying] = useState(false)
  return (
    <Fragment>
      {!playing && <h1>Whac a Mole</h1>}
      <button onClick={() => setPlaying(!playing)}>{playing ? 'Stop' : 'Start'}</button>
      {playing &&
        <Fragment>
          <Score/>
          <Timer
            time={TIME_LIMIT}
            onEnd={() => setPlaying(false)}
          />
          <Moles>
            <Mole/>
            <Mole/>
            <Mole/>
            <Mole/>
            <Mole/>
          </Moles>
        </Fragment>
      }
    </Fragment>
  )
}

render(<Game/>, document.getElementById('app'))
View Compiled

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.