How to Build a ReactJS based Hangman game

Designing and building a hangman game is a common task in a programming job interviews. Here we’ll explain our own implementation for it using ReactJS: Create a new project -> Do some component design -> Add business logic -> polish our CSS -> Jumping around happy.

TLDR; The code for this project can be found in my github here, would appreciate your stars and comments 🙂

Credit to cover image goes to: skeeze from Pixabay

This is a followup post that provides a tutorial to build React+ES6+Webpack hangman game implementation. This answers the “hangman job interview question for front end developers“.

Our goal is to code the hangman game, and more than that – to do it in the way I really work in real life.

At the end it should look like this:

How to Build a ReactJS based Hangman game - this is the goal for our project

There are many tutorials and guides out there. What makes this one unique is that I don’t know how the project will look like when it will be ready. Also, it will be developed in the order of things that I do when working on a REAL project – by iterations, not perfect from the start.

My development order will be something like:

  • have a boiler plate project running with React and Webpack
  • Do the component design
  • Code the components with some basic CSS
  • Add business logic
  • Test a few cases
  • Polish the CSS again
  • Add a deployment pipeline.
  • Go over the code to make it prettier, making sure it’s human readable
  • Sleep

First step – clone a boiler plate project

Google offered a few options for an empty es6+webpack+react boiler plate project. I chose this one, running this command on my terminal:

This project have already defined a development server for us that runs on port 8080, transpiles es6 into regular java script, and can handle ReactJS. More than enough for me at the moment.

git clone https://github.com/HashemKhalifa/webpack-react-boilerplate.git

After cloning complete, install the project’s dependencies using:

npm i

and then start the server

npm start

now open the browser and go to localhost:8080, you should see the nice hello world looking at you.

Need some help? you are welcomed to leave a comment, or visit the github page of the project at https://github.com/HashemKhalifa/webpack-react-boilerplate.

The Hello World code we just checked out (cloned) has 2 interesting parts. App.jsx file – the root of the project.

HelloWorld folder, with index.jsx in it.

App.jsx imports HelloWorld component and uses it.

As a first step, I’ll play with the HelloWorld component, to see I can work with this project, and to make sure the hot module replacement plugin works and my changes are displayed instantly,

I tried to change the color of the text to red, did it in file called: hello-world.css

works, let’s start designing our own app.
The hard part is behind us, now – to work!

Component design for ReactJS hangman game

This is what I have in mind for now:

A. Some kind of wrapper component (maybe the App.jsx itself?).

B. Inside the wrapper a component with the current state of the game, that holds:
(1) The hanged man drawing according to the number of errors.
(2) A component that holds the word with gaps.

And another component inside the wrapper, that handles the user input, validation, the submit button, etc.

In a drawing, perhaps clearer:

How to Build a ReactJS based Hangman game: Component design for hangman game, using React components. This is the second step on our hands on a step by step react tutorial

This design is not perfect, but it will do for now. Note to self – forget about CSS for now.

First make it work, then make it pretty.

@RanEilam, my first guru

When coding these component, I prefer to start from the container/wrapper, and then make the components inside of it. It makes you also think what kind of data each of the components need, and what should it do.

For example, the Letter component obviously needs to get the letter to show as an input, but what happens when the user didn’t reveal that letter yet? In that case we would want to keep the space (width) for it, but not to show it. A show=true prop will do the trick.

For me, the project structure has a big significance in making my mind cleared about what I need to do. So I copied the HelloWorld component from the original repo, and created these component. For now – the don’t do anything, perhaps even don’t compile. doesn’t matter.

This is the project structure we have at the moment, each component has it’s own JSX file, and own CSS file imported from the JSX file.

How to Build a ReactJS based Hangman game: File structure that supports the Component design for hangman game, using React components. This is the second step on our hands on a step by step react tutorial

Connecting the components together is now our goal.

  1. App.JSX should render the game status and user interaction.
  2. Game-status.jsx should render the painted status and the word display
  3. word-display.jsx should render the letters
  4. user-interaction.jsx should show an input field and a button

After connecting them, and fixing all the broken imports, it still looks ugly. For example, the game-wrapper.jsx component code looks like this:

How to Build a ReactJS based Hangman game: Example for the code of a file called game-wrapper.jsx. Part of the Component design for hangman game, using React components. This is the second step on our hands on a step by step react tutorial

See stuff on the browser for the first time

As said, it looks like a mess.. a bit of CSS to make it better, not perfect.

I’ll start by adding some standard rules to the game-wrapper’s CSS (game-wrapper.css), first one will be
box-sizing: border-box;

What is box sizing? here

Now, to make it look OK, we’ll make each component return a static HTML snippet, a text maybe. The Letter.jsx component will return the letter L, the painted status will return the text “5 Errors”, and the user interaction component will return a button and the text “Enter a letter”.

This is what we got:

How to Build a ReactJS based Hangman game: This is how the page looks like after making the components return static data, no logic or CSS yet. This is the second step on our hands on a step by step react tutorial
All the components are there, without any CSS or logic

One last thing to make it a bit easier to style, is to replace the “5 Errors” with an actual image. I painted one in MSPaint, and converted to base 64 using this service, so I could use it. You can make the painted-status component return an img tag containing this image.

And it will show this image

How to Build a ReactJS based Hangman game: using temp image
A temp image of the hangman status, to be used for later styling

First round of CSS

Our goal now is to make the screen look better, not to polish yet.

To do so, I’ll focus on each component giving it very basic CSS attributes, starting from the game wrapper.

Because I would like to use flex box for components alignment, I’ll define the game-wrapper to contain flex box elements. And some padding from the top of the screen.

 .game-wrapper {
box-sizing: border-box;
display: flex;
flex-direction: column;
padding-top: 20px;
}

Each of the game-wrapper’s children will get a flex: XXX; rule as well. I think a 5 to 1 ratio makes sense between the status and the input parts, so I added:

.game-status{
flex: 5;
display: flex;
flex-direction: column;
}

.user-interaction {
display:flex;
flex-direction: row;
justify-content: space-between;
padding-top: 40px;
font-size:30px;
flex: 1;
}

Actually, I added display: flex; rule to all parent components.

The flex-direction: column; rule makes them paint the child elements from top to bottom, instead of the default left to right.

To make the app in the center of the screen we used the margin: 0 auto; method. There are other ways to do it as well.

Also, added some style to the Letter.jsx component, so it will look a bit better, copied style from here

Now it looks like this:

How to Build a ReactJS based Hangman game: after first round of CSS
The hangman app – centered, with a stylish Letter component

Before diving into the logical part, let’s add some style to the input button and text at the bottom.

To make it work, we added an input field, with a limit of one character, and made it all centered with justify-content: space-between; rule.

Now it looks like this:

How to Build a ReactJS based Hangman game: A pretty styled hangman using ReactJS component, and flex-box based CSS.
A pretty styled hangman using ReactJS component, and flex-box based CSS.

Thanks for reading so far. I thought it’s gonna be a single post, but it’s starting to be supppper long. So that’s it for now.

Where is the code?

You can find the code of this project right here in github: https://github.com/AsafShochet/hangman-es6-react-webpack

feel free to clone and comment.

Enters the business logic

A short wrap up: We are on a journey to develop a hangman game app using ReactJS. So for we created a project configured with webpack, es6 and React, created components and added basic CSS.

Now it’s time to add the logical part of the game, add deployment script that bundles the app and uploads it to Heroku, and tidy up the CSS.

Out app looks like this at the moment:

How to Build a ReactJS based Hangman game: Hangman game pretty styled, with all components in placeHangman game pretty styled, with all components in place
Hangman game pretty styled, with all components in place

The source code for this tutorial can be found here: https://github.com/AsafShochet/hangman-es6-react-webpack

I imagine that in the end of the project there will be a server that saves the states, and chooses a word to guess according to the user’s preference. For now we will not use a server.

General approach to the business logic

Although this is a “React” JS application, and it is attempting to put the logic inside the components themselves, it’s considered a bad practice.

What we WILL want is to separate the business logic from the component. For that I’ll create a “services” layer. The services will be responsible for actions like:

  • Choosing a word to guess for the user.
  • Checking if the user guessed correctly or not.
  • More things to come (?)

This means that I’m adding the /services folder under the src folder.

How to Build a ReactJS based Hangman game: React es6 webpack hangman tutorial.
This is the phase where we are adding a services folder. All the business logic actions will be handled there.
Adding a services folder under src folder. All business logic actions will be handled there.

Choosing a random word

Our first service! In real life I assume this will be done in the server. But here, we’ll do it in the service itself.

I will make the method that generates a random word return a promise, so in the future it will be easy to replace it with a real XHR to the server.

This is what I came up with

How to Build a ReactJS based Hangman game: word generator class to return a promise resolved with the selected word
Word generator class to return a promise resolved with the selected word

Great, now we can generate the word. Let’s make the App call it on initialization and start passing it to the correct places in our app.

looks like this:

How to Build a ReactJS based Hangman game: App jsx now holds a simple user state, calls the "server" and sets the word to show
App jsx now holds a simple user state, calls the “server” and sets the word to show

This is the phase that I check that the app “compiles” and I can still see things on the browser. Most of the times it doesn’t on the first try, so analyzing the errors helps.

Now, I’ll add a simple error counter to show the number of errors in the PaintedStatus component, and make the Letter component show the correct word. It will be ugly but will show the counter.

Showing image by number of errors

You know what, I think it’s time to add the images. Because we are using webpack, it’s a good idea to use the file-loader. You can read about it here: https://stackoverflow.com/questions/37671342/how-to-load-image-files-with-webpack-file-loader

Importing the files using this plugin makes the build process add the images to the /dist folder, so it will be there when deployed. you can see them under resources/images here: https://github.com/AsafShochet/hangman-es6-react-webpack

ReactJS hangman – Managing the game state

I thought about the state of the game and how can it be modified during the game. When the user submits a letter, it needs to be:

  1. validated (to see it is a letter)
  2. check that the letter is part of the word or not
  3. cause a change in the game status area of the screen – changing the word itself and the hangman drawing.

To do so, we’ll have a “state” inside the GameWrapper.jsx, that will be changed after submit. As it looks at the moment – the GameWrapper is going to be our smartest component.

You can read more about smart components here

The state should have all the data that will be changed during the game from the GameWrapper component itself or from its child components.

How to Build a ReactJS based Hangman game: Initial state for the GameWrapper.jsx component
Initial state for the GameWrapper.jsx component

Every time the user submits a new letter, the GameWrapper will check if this letter exists or not in the word, and will update the errorCount accordingly. Also, if the user guessed all the letters before the game is over it will set the userWon parameter to be true.

These parameters will be passed to child components to show the right picture and right word with blanks.

Now, to make the submit button send the correct letter, I wrapped the input text and button in a simple <form> tag, and then added a callback to the onSubmit of the form. Like the first example here: https://reactjs.org/docs/forms.html

How to Build a ReactJS based Hangman game: user-interaction.jsx render method, showing how to use ReactJS forms to submit a single letter.
user-interaction.jsx render method,
showing how to use ReactJS forms to submit a single letter.

Adding the glue between the components makes us to test and see that all the data passes from place to place. That’s good.

For now – we have a working game, pretty nice!

Conclusion:

We started by creating a new project from an existing boiler plate repository we found on github. Then, designed the components to be used in the game and created very dumb components. Afterwards we added some CSS to make it look better, and only then we added the business logic to make it do what we want.

*** There are other ways to do it ***

And maybe I will choose a different way or approach next time.

Hope you enjoyed, please comment and tell what do you think 🙂