Tic-Tac-Toe.js: redux pattern in plain javascript

May 2, 2016 · 4 min read
Image for post
Image for post
Check github repo or play the game.

There’s this thing going on in the Front-End Development community where everybody wants to re-write their applications to use React. Sorry to disappoint, but that’s not the case here. At work I mostly use vanilla javascript, therefore it is more beneficial for me to learn the concepts rather than the frameworks themselves.

With the amazing help and guidance of @ricardobeat, I’ve managed to build this Tic-Tac-Toe game using Redux principles with vanilla javascript. No React, no jQuery, no micro-library, it doesn’t rely on anything else. It’s just plain JS. Isn’t it great? In this post I’d like to share the approach that made this possible. Let’s get into the details.

The key principles

The Redux pattern is mainly based on three fundamental principles:

How does it look on Tic-Tac-Toe.js?

1. One single store
Everything that can affect UI is saved on store.js. This is what the store looks like:

Check full source code.

2. Game.js dispatches actions whenever needed
Let’s see what happens, for instance, when user clicks on the table grid:

Check full source code.

3. Reducers receive actions and return new state

Check full source code.

4. Render UI when store gets updated
It’s pretty straightforward. Every time the store gets updated it notifies the subscribers so they can update the UI accordingly.

Check full source code.

In the above case I’m doing it slightly different compared to store.subscribe(render) in Redux. I’m actually triggering a global event and letting game.js render the callback whenever necessary.

Update: I've changed from global event emitter to store.subscribe approach to simplify the code.

The important thing here is that we stick with the correct data flow. Which brings me to next topic.

Strict unidirectional data flow

Image for post
Image for post

Maybe you haven’t noticed, but on previous examples the data flow is always unidirectional. Game.js — the view — dispatches actions, store.js receives and process them with reducers which later triggers 'store:update' so finally we can render the UI updates.

You can read more about Data Flow on redux.js.org.

Going multiplayer

Ok, we have everything working on the client-side. But how is Tic-Tac-Toe connecting two players?

Implementing the back-end in node.js + socket.io was really simple and that’s one of the coolest things about Redux. Because everything is based on actions, which are by definition simple objects, the only requirement on the Back-end would be: receiving the action and dispatching it to other players connected in the same room/game id.

The front-end side:

Everything starts on the client-side. When the page loads I generate a random ID, which will then be handed to the server.

Check full source code.

The back-end side:

It’s all about registering the room and broadcasting the actions:

Check full source code.

Design and usability

The game was designed to work in different resolutions. On desktop version the favicon updates according to the player turn, check that out when you start playing. On mobile it’s possible to save the app on home screen, there’s a special logo icon for that.

“Ok, so how can I play the game?”

Is there an easier way to connect in the same room?

If you are using iOS you can share your browser url using AirDrop. That way your friend would load the same room/game id by default.


Redux has proven to be very easy to debug and fix issues. You have one single entity that represents the state of your application and the only way you can change it is by dispatching actions. I was also surprised how fast it was to integrate with a node.js server and make it broadcast certain actions to the front-end.

I’ve learned a lot of cool things working on this project and I hope you find this post useful. Check out Tic-Tac-Toe.js on github and have fun! :)

Update: I've spoken about this topic @ React Amsterdam meetup. Check out the video below. Slides are also available on Speaker Deck.


Written by

I’m a Front-End Engineer at Booking.com. JavaScript, HTML and CSS are my UX Design tools. My personal goal: learning something new every day.


Written by

I’m a Front-End Engineer at Booking.com. JavaScript, HTML and CSS are my UX Design tools. My personal goal: learning something new every day.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch

Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore

Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store