Create Games using: React-Redux
I created a game using React for Mod-4 during Flatiron Bootcamp for Software Engineering.
The game is called Air-Patrol, which illustrates the impact on the environment when trees get cut down and how that effects the atmosphere, the player has to make tough decisions to keep the balance of the air quality under control.
The game originally was built only with React, which is much better and faster to implement than Mod-3 using vanilla JavaScript, where you implement all JS code in index.js.
The downside about having so many components is passing down props from a parent component to its children.
And here Comes Redux so handy to pass your props to any component in your app.
First what is Redux? — Redux is an open-source JavaScript library for managing application state. It is most commonly used with libraries such as React or Angular for building user interfaces.
On the right side, You can see Store, which will be the cloud that holds your state and you will be able to call that store anywhere using the Connect.
You probably be better off reading the documentation of Redux which is very cool and easy to understand, but over here I will explain how to use redux to build a game.
Building a game requires a lot of functionalities and every function goes back to your store to manipulates something, increase or decrease.
To implement a good Redux system, You need to understand two things
- Reducers
- Action Creators
You will always have these two open all the time, and the more you practice and write them, the faster you’ll become an expert
1- Reducer:
Reducers specify how the application’s state changes in response to actions sent to the store. Remember that actions only describe what happened, but don’t describe how the application’s state changes.
- A perfect start for a reducer would be the state that you will want to have access to, in other components such as :
const defaultState = {
currentUser: null,
atmosphere: null,
score: 0, // User progress
timer: 180,
oxygen: 0,
carbon_dioxide: 0,
water: 0
}
It’s important to have those in my state so when users login or signup, it assigns currentUser and use user’s information thru functions as well as keeping the score and incrementing or decrementing it.
Second is how to implement the reducer function itself?
Reducer is a function that takes the State you just declared and an Action object that looks like this {type: “DO_SOMETHING”}
In other words you pass an order to the function to manipulate the state like this example:
case 'INCREASE_SCORE':return { ...state, score: state.score += 10 }
Here I have an action.type INCREASE_SCORE to increase the state.score by 10.
It’s very easy right, not quite, here comes the part I was struggling with.
- ACTION CREATORS:
Actions are payloads of information that send data from your application to your store. They are the only source of information for the store. You send them to the store using store.dispatch()
.
Once I understood this, everything has clicked about the importance of redux.
- Let’s create an Action creator together:
touch actionCreator.js
export const increaseScore = () => ({ type: 'INCREASE_SCORE' })
- We export the function to use it at any component
- increaseScore is the name of the function with an object “action” that has a type to INCREASE_SCORE
So how do we use all of this and in what order does it work behind the seen ?
After creating the Game.js component
import React from 'react';class Game extends React.component {render() {
return (
<div>
<p> Name: </p>
<p> Score: </p>
</div>
)
}}
export default Game
We will need to connect the store, before you do this, read React-Redux docs for how to install redux and wrap your store into the provider, also how to create your store using createStore in index.js
Simply by importing “connect” from “react-redux” at any component you want to have access to the Store.
import { connect } from 'react-redux'
Now our component will look like this
import React from 'react';
import { connect } from 'react-redux'class Game extends React.component { render() {
return (
<div>
<p> Name: {this.props.currentUser.name} </p>
<p> Score: {this.props.score} </p>
</div>
)
}}
const msp = state => {
return {
currentUser: state.currentUser,
score: state.score
}
}export default connect(msp)(Game)
We need MSP which is short for “MapStateToProps”, it’s a function that comes with connect to map over the state in the Reducer to pass them to your component as props, in this component I selected both CurrentUser and score.
Now lets import our Action creator:
import React from 'react';
import { connect } from 'react-redux'
import increaseScore from '../actionCreator'class Game extends React.component {render() {
return (
<div>
<p> Name: {this.props.currentUser.name} </p>
<p> Score: {this.props.score} </p>
<button onClick={() => this.props.increaseScore}>
Increase Score
</button> </div>
)
}}
const msp = state => {
return {
currentUser: state.currentUser,
score: state.score
}
}export default connect(msp, { increaseScore })(Game)
Lets break it down:
- First we imported the action creator and added it to connect.
- Connect takes two arguments MSP and MDP
- MDP is short for MapDispatchToProps which is the same thing like MSP which maps thru the state, instead MDP maps thru functions.
- Unlike MSP you can just import the function and add it to the second argument which is an object.
- If you have more than one functions you can add them all in the second argument like this
export default connect(msp, { increaseScore, decreaseScore })(Game)
- If you only want to connect MDP and no State props are needed in this component, add null for the first argument
export default connect(null, { increaseScore })(Game)
3- Now that we implemented a successful Redux Action Creator Let me explain:
- First you call the function from the action creator
<button onClick={() => this.props.increaseScore}>
Increase Score
</button>
- The function goes to the Action Creator
export const decreaseScore = () => ({ type: 'INCREASE_SCORE' })
- This is an Action object that has a type: ‘INCREASE_SCORE’ and goes to the main Reducer function to check which case has ‘INCREASE_SCORE’
- At our Reducer we have a case for ‘INCREASE_SCORE’
function reducer(state = defaultState, action) { switch (action.type) { case 'INCREASE_SCORE': return { ...state, score: state.score += 10 } case 'DECREASE_SCORE': return { ...state, score: state.score -= 10 } default: return state }
}
that returns the same state, but manipulate the score by incrementing 10 to it and React reacts towards that new state and shows it on the screen.
Conclusion and pros about using Redux:
- Redux would not just save time by passing the right props anywhere, but cleans the component’s code and makes it look professional.
- Air-Patrol has over 30 functions so far, and to be able to write them in one page and import any function you need is amazing.
- It’s very difficult to implement redux on a React project as tracking down functions and props would defiantly be frustrating, instead create project using Redux from scratch which won’t take much time if you have your functions ready.
- Defiantly you will need to learn about Thunk and Async functions for certain GET fetch requests.
- Redux is being used for most games built with JavaScript and it’s very needed in today’s Job Market.
Next Blog I will write about pros and cons of using Function vs Class components using Redux and React LifeCycles which is very necessary if you build a game.
Cheers!
Mocha