Component Breakdown & State Management ⚙ - Building a tic-tac-toe game with React from scratch
Tags: javascript, react, gamedev, webdev
Published: 2022-07-04 05:41:35

Welcome! 👋

_ℹ️ This post is part of a series, where I pen down my journey as I plan and build a tic-tac-toe game from ideation to release_

In the [previous post](https://dev.to/alimansoorcreate/building-a-tic-tac-toe-game-with-react-from-scratch-wireframing-design-2nn5), we designed the app's UI, from displaying the start screen to displaying the result of a tic-tac-toe game:

![User flow diagram](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mf012ek8yrnj50al6qqv.png)
 

The React mindset dictates that user interfaces be broken down into individual components, each of whom performs a single task. This will help us abstract away irrelevant logic while developing the app and reuse code whenever possible. Let's understand this with an example:

![Game screen with player names labelled](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/g7qfjqcfksllf3ylr9r4.png)
 
In this screen, we can see some repetition happening in the form of a piece of UI that displays a player's name and mark (inside the dotted square). 

We can either write code to display both player's details separately, or we can create a single component that accepts a player's details as parameters, and then handles displaying those details itself. We can then use that component twice, telling it to display a different player each time:

![Now using a component with different parameters each time](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0iz7sli9gxeu9ow8n588.png)

Hence we only need to write the code to display details once and can reuse it for both players!

Seeing the clear benefit of this approach, let us go ahead and break our app's UI down into individual components. We will start off with the three screens:

1. Start
2. Settings
3. Game

All other components would be children of these, and each of these represents a different section in the user flow. Therefore we could also call them _page/layout components_.

## 1. Start

![Start component](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tw6yi1rz60um1yekk10n.png)
 
The `Start` page will consist of only two components: `StartButton`, and `Attribution`. Displaying the X and O in the background can be handled by `Start` itself.

## 2. Settings

![Settings component](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9mjd18jc3h5mvajfnpo0.png)
 
The `SettingsForm` component will house and lay out the `SelectGameMode`, `SelectGridSize`, and `EnterPlayerNames` components, each of which will enable the user to edit the game settings. `EnterPlayerNames` will house 2 instances of `PlayerNameField`, which will allow editing the name of a single player.

When the game mode is PvP, both fields will be editable, whereas in PvC, only the player 1 field will be editable and the player 2 field will contain the uneditable text "A.I."

## 3. Game

![Game component](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xpk7pay82mqu8aybu8ne.png)
 
The top section of the game screen will be contained in `GameHeader` and the rest of the components will be direct children of `Game`.

`Grid` will render a square grid of `GridCell` components, and each `GridCell` will update its background color and image appropriately when it is clicked or when there is a match.

![Game component result state](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/adhd42cjg4hq2yvg3rbz.png)
 
When the game ends, the `Result` component will be displayed, stating the outcome, and `RestartButton` will become highlighted, to probe the player(s) to play another game.

Let us now think about the data that our game will need to keep track of.

## Defining data

React applications work with data that may frequently change and the UI needs to update in respond to these changes. Such data is called state, and it can be stored either in the global scope, where it is accessible to all components, or in the component scope, where it is accessible to only a single component and optionally its children. State management libraries like [Redux](https://redux.js.org/) allow us to store data in the global scope and write methods to access and change it.

It is good practice to store data that is related to the business logic in the global scope, and that which is related to UI/component logic in the component scope.

We can understand this with the example of an online shopping site. The items in your cart would be stored in the global scope, but whether the cart is currently open/visible or closed/hidden would be stored in the component representing the cart itself.

Using this convention, we can extract the following data to be stored in the global scope of our application:

- Game mode: string containing either "PvC" or "PvP" 
```typescript
type GameMode = "PvC" | "PvP"
```
- Grid size: the number 3, 4, or 5 
```typescript
type GridSize = 3 | 4 | 5
```
- Players: array containing 2 player objects,
        where each player object stores the type of player ("human"/"ai"), the name of player, and their score 
```typescript
type Players = [Player, Player]

type Player = {
  type: "human" | "ai"
  name: string
  score: number
}
```
- Grid: array containing child arrays, each of which contains cell objects, where each cell object stores its mark (""/"X"/"O") and whether it is part of a match
```typescript
type Grid = Cell[][]

type Cell = {
  mark: "" | "X" | "O"
  match: boolean
}
```
- Current player: number, either 0 or 1, representing the index of the current player
```typescript
type CurrentPlayer = 0 | 1
```
- Game end: object representing whether a match has been made, whether there has been a draw and whether the game has ended
```typescript
type GameEnd = {
  match: boolean
  draw: boolean
  end: boolean
}
```

We now have ourselves the following global state tree:

```typescript
{
  gameMode,
  gridSize,
  players,
  grid,
  currentPlayer,
  gameEnd
}
```

Now that we have a solid component hierarchy, as well as a global state tree, we can finally start the development process.

⚡ Join me in the next post in this series, where we will set up our development environment and build the first two pages of the app

❤️ Remember to like this post and leave your thoughts in the comments!