Skip to main content

Letter game

· 3 min read
Filip Tammergård
Software Engineer at Frilans Finans

Start the game by clicking the input box and then pressing space. The clock starts and you get a random letter to type as fast as you can. Each correct letter is followed by a new random letter, and if you type the wrong letter, the game ends. Go for it!

Press space to start

0.00 s

The code behind the letter game

This game is built in React (with TypeScript). React is really nice to work with and I think the code behind this simple game gives a small glimpse of why I dig React.

useState

One thing in the code that's unique to React is handling state with useState hooks.

const [isRunning, setIsRunning] = useState<boolean>(false)
const [time, setTime] = useState<number>(0)
const [letter, setLetter] = useState<string>("")
const [correct, setCorrect] = useState<number>(0)
const [score, setScore] = useState<number>(0)
const [highscore, setHighscore] = useState<number>(0)

This handles all the data the game needs to keep track of — everything from whether the game is running to what the record is. Initial values for each state are set here, and since I use TypeScript I've also declared the data type for each state.

useEffect

Another nice thing about React is useEffect. With useEffect, you can make sure certain things only run when they need to.

useEffect(() => {
const savedHighscore = window.localStorage.getItem("letter_game_highscore")
if (savedHighscore != null) {
setHighscore(Number(savedHighscore))
}
}, [])

The record is stored in local storage, so every time the page reloads I want to start by checking local storage for a saved record. If a record exists, I save it to state. As long as the page isn't reloaded, local storage doesn't need to be checked again. But how do we make sure the check only happens once? That's where useEffect comes in. The empty array tells React this effect should only run once.

Custom hooks

useState and useEffect are examples of hooks built into React. You can also create your own hooks. One piece of functionality I use fairly often is some kind of timing or having something happen on an interval. This can be done with the JavaScript function setInterval, but to make it a bit smoother I've extracted setInterval handling into a custom hook called useInterval. See more details in Custom hook: useInterval.

My own useInterval hook makes it possible to do timing in a very simple way:

useInterval(
() => {
setTime(time + timerFrequency)
},
isRunning ? timerFrequency : null,
)

In plain English the implementation of useInterval works like this:

If the game is running, add to the time the time that has passed since the last tick. If the game is not running, stop the interval.