I am one of those developers who likes to do things from scratch and get to know how everything works. Although I am aware of the (unnecessary) work I get myself into, it definitely helps me appreciate and understand what lies behind a specific framework, library, or module.
Made by Facebook, React is a component-based, open source library for building user interfaces. While React is only a view layer (not a full framework such as Angular or Ember), Redux manages the state of your application. It functions as a predictable state container, where the entire state is stored in a single object tree and can only be changed by emitting a so called action. If you’re completely new to the topic, I recommend checking out this illustrative article.
For the rest of this article it’s not required to be an expert on Redux, but it definitely helps to have at least a basic understanding of its concepts.
An Application from Scratch
What makes Redux great is that it forces you to think ahead and get an early picture of your application design. You start to define what should actually be stored, which data can and should change, and which components can access the store. But since Redux is only concerned with state, I found myself a bit confused as to how to structure and connect the rest of my application. React does a good job of guiding you through everything, but without it, it was down to me to figure out what works best.
The application in question is a mobile-first Tetris clone, which has a couple of different views. The actual game logic is done in Redux, while the offline capabilities are provided by
localStorage, and custom view handling. The repository can be found on GitHub, though the application is still in active development and I am writing this article as I work on it.
Defining the Application Architecture
I decided to adopt a file structure commonly found in Redux and React projects. It’s a logical structure and is applicable to many different setups. There are many variations on this theme, and most projects do things a little differently, but the overall structure is the same.
actions/ ├── game.js ├── score.js └── ... components/ ├── router.js ├── pageControls.js ├── canvas.js └── ... constants/ ├── game.js ├── score.js └── ... reducers/ ├── game.js ├── score.js └── ... store/ ├── configureStore.js ├── connect.js └── index.js utils/ ├── serviceWorker.js ├── localStorage.js ├── dom.js └── ... index.js worker.js
My markup is separated into another directory and is ultimately rendered by a single
index.html file. The structure is similar to
scripts/, so as to maintain a consistent architecture throughout my code base.
layouts/ └── default.html partials/ ├── back-button.html └── meta.html pages/ ├── about.html ├── settings.html └── ... index.html
Managing and Accessing the Store
To access the store, it needs to be created once and passed down to all instances of an application. Most frameworks work with some sort of dependency injection container, so we as a user of the framework don’t have to come up with our own solution. But how could I make it accessible to all of my components when rolling my own solution?