Skip to content

Commit

Permalink
feat: step 4 - introduced redux and react-redux
Browse files Browse the repository at this point in the history
  • Loading branch information
Antoine Lelaisant committed Mar 12, 2021
1 parent 31a0c7b commit f730084
Show file tree
Hide file tree
Showing 13 changed files with 142 additions and 77 deletions.
1 change: 1 addition & 0 deletions jsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,6 @@
"paths": {
"assets": ["./assets/*"],
"components": ["./components/*"]
"modules": ["./modules/*"]
}
}
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@
"prop-types": "^15.7.2",
"react": "^17.0.1",
"react-dom": "^17.0.1",
"react-redux": "^7.2.2",
"react-router-dom": "^5.2.0",
"react-scripts": "4.0.2",
"redux": "^4.0.5",
"web-vitals": "^1.0.1"
},
"scripts": {
Expand Down
10 changes: 7 additions & 3 deletions src/components/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,29 @@ import {
Switch,
Route,
} from 'react-router-dom'
import { Provider } from 'react-redux'
import CssBaseline from '@material-ui/core/CssBaseline'
import './App.css'
import { Game } from './Game'
import { Home } from './Home'
import configureStore from '../configureStore'

const store = configureStore()

export const App = () => {
return (
<>
<Provider store={store}>
<CssBaseline />
<Router>
<Switch>
<Route exact path="/">
<Home />
</Route>
<Route path="/">
<Route path="/game">
<Game />
</Route>
</Switch>
</Router>
</>
</Provider>
)
}
50 changes: 10 additions & 40 deletions src/components/Game/Game.js
Original file line number Diff line number Diff line change
@@ -1,70 +1,40 @@
import React, { useState, useEffect } from 'react'
import './Game.css'
import React, { useEffect } from 'react'
import { useDispatch } from 'react-redux'
import Paper from '@material-ui/core/Paper'
import './Game.css'
import { loop } from 'modules/game'
import { Navbar } from 'components/layout/Navbar'
import { Gitcoin } from 'components/Gitcoin'
import { Score } from 'components/Score'
import { Store } from 'components/Store/Store'
import { Skills } from 'components/Skills'
import items from '../../items'

export const Game = () => {
const [lines, setLines] = useState(0)
const [linesPerMillisecond, setLinesPerMillisecond] = useState(0)
const [ownedItems, setOwnedItems] = useState({})
const dispatch = useDispatch()

useEffect(() => {
const interval = setInterval(() => {
setLines(lines + linesPerMillisecond)
dispatch(loop())
}, 100)

return () => clearInterval(interval)
})

useEffect(() => {
let count = 0

Object.keys(ownedItems).forEach(name => {
const item = items.find(element => element.name === name)
count += item.multiplier * ownedItems[name]
})

setLinesPerMillisecond(count)
}, [ownedItems])

const handleClick = () => {
setLines(lines + 1)
}

const handleBuy = item => {
setLines(lines - item.price)
setOwnedItems({
...ownedItems,
[item.name]: (ownedItems[item.name] || 0) + 1
})
}

return (
<>
<Navbar />
<main className="game">
<Paper elevation={3} className="left">
<Score
lines={lines}
linesPerSecond={parseInt(linesPerMillisecond * 10)}
/>
<Gitcoin onClick={handleClick} />
<Score />
<Gitcoin />
</Paper>

<Paper elevation={3} className="center">
<Skills skills={ownedItems} />
<Skills />
</Paper>

<Paper elevation={3} className="right">
<Store
lines={lines}
onBuy={handleBuy}
/>
<Store />
</Paper>
</main>
</>
Expand Down
15 changes: 8 additions & 7 deletions src/components/Gitcoin/Gitcoin.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
import React from 'react'
import PropTypes from 'prop-types'
import { useDispatch } from 'react-redux'
import './Gitcoin.css'
import { click } from 'modules/game'
import githubIcon from 'assets/github.svg'

export const Gitcoin = ({ onClick }) => {
export const Gitcoin = () => {
const disptach = useDispatch()

const handleClick = () => disptach(click())

return (
<button
className="gitcoin"
onClick={onClick}
onClick={handleClick}
>
<img src={githubIcon} alt="Gitcoin" />
</button>
)
}

Gitcoin.propTypes = {
onClick: PropTypes.func.isRequired,
}
2 changes: 1 addition & 1 deletion src/components/Home.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export const Home = () => {
<div className={classes.heroButtons}>
<Grid container spacing={2} justify="center">
<Grid item>
<Link to="/gitclicker">
<Link to="/game">
<Button variant="contained" color="primary">
Play
</Button>
Expand Down
20 changes: 10 additions & 10 deletions src/components/Score.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import React from 'react'
import PropTypes from 'prop-types'
import { useSelector } from 'react-redux'

export const Score = ({ lines, linesPerSecond }) => (
<>
<h3 style={{fontFamily: 'Orbitron'}}>{parseInt(lines)} lines</h3>
<small>per second: {linesPerSecond}</small>
</>
)
export const Score = () => {
const lines = useSelector(state => parseInt(state.game.lines))
const linesPerSecond = useSelector(state => parseInt(state.game.linesPerMillisecond * 10))

Score.propTypes = {
lines: PropTypes.number.isRequired,
linesPerSecond: PropTypes.number.isRequired,
return (
<>
<h3 style={{fontFamily: 'Orbitron'}}>{lines} lines</h3>
<small>per second: {linesPerSecond}</small>
</>
)
}
10 changes: 4 additions & 6 deletions src/components/Skills/Skills.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import React from 'react'
import { useSelector } from 'react-redux'
import './Skills.css'
import PropTypes from 'prop-types'
import Typography from '@material-ui/core/Typography'
import { Section } from './Section'

export const Skills = ({ skills }) => {
export const Skills = () => {
const skills = useSelector(state => state.game.skills)

return (
<>
<Typography variant="h5">Skills</Typography>
Expand All @@ -20,7 +22,3 @@ export const Skills = ({ skills }) => {
</>
)
}

Skills.propTypes = {
skills: PropTypes.objectOf(PropTypes.number).isRequired,
}
19 changes: 11 additions & 8 deletions src/components/Store/Store.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,19 @@
import React from 'react'
import PropTypes from 'prop-types'
import { useSelector, useDispatch } from 'react-redux'
import Typography from '@material-ui/core/Typography'
import './Store.css'
import { buyItem } from 'modules/game'
import { Item } from './Item'
import items from '../../items'

export const Store = ({ lines, onBuy }) => {
export const Store = () => {
const dispatch = useDispatch()
const lines = useSelector(state => state.game.lines)

const handleBuy = item => {
dispatch(buyItem(item))
}

return (
<div className="store">
<Typography variant="h5">Store</Typography>
Expand All @@ -15,14 +23,9 @@ export const Store = ({ lines, onBuy }) => {
key={key}
item={item}
lines={lines}
onBuy={onBuy}
onBuy={handleBuy}
/>
)}
</div>
)
}

Store.propTypes = {
lines: PropTypes.number.isRequired,
onBuy: PropTypes.func.isRequired,
}
8 changes: 8 additions & 0 deletions src/configureStore.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { createStore } from 'redux'
import { rootReducer } from './modules'

export default () => {
const store = createStore(rootReducer)

return store
}
53 changes: 53 additions & 0 deletions src/modules/game.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// Actions
const CLICK = 'game::CLICK'
const BUY_ITEM = 'game::BUY_ITEM'
const LOOP = 'game::LOOP'

// Action creators
export const click = () => ({
type: CLICK,
})

export const buyItem = item => ({
type: BUY_ITEM,
item
})

export const loop = () => ({
type: LOOP
})

const INITIAL_STATE = {
lines: 0,
linesPerMillisecond: 0,
skills: []
}

export const reducer = (state = INITIAL_STATE, action) => {
const { type } = action

if (type === LOOP) {
return { ...state, lines: state.lines + state.linesPerMillisecond }
}

if (type === CLICK) {
return { ...state, lines: state.lines + 1 }
}

if (type === BUY_ITEM) {
const { item: { name, price, multiplier }} = action
const { skills, lines, linesPerMillisecond } = state

return {
...state,
lines: lines - price,
linesPerMillisecond: linesPerMillisecond + multiplier,
skills: {
...skills,
[name]: (skills[name] || 0) + 1
}
}
}

return state
}
6 changes: 6 additions & 0 deletions src/modules/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { combineReducers } from 'redux'
import { reducer as game } from './game'

export const rootReducer = combineReducers({
game
})
23 changes: 21 additions & 2 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -9773,7 +9773,7 @@ react-error-overlay@^6.0.9:
resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-6.0.9.tgz#3c743010c9359608c375ecd6bc76f35d93995b0a"
integrity sha512-nQTTcUu+ATDbrSD1BZHr5kgSD4oF8OFjxun8uAaL8RwPBacGBNPf/yAuVVdx17N8XNzRDMrZ9XcKZHCjPW+9ew==

react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.1:
react-is@^16.13.1, react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.1:
version "16.13.1"
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
Expand All @@ -9783,6 +9783,17 @@ react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.1:
resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.1.tgz#5b3531bd76a645a4c9fb6e693ed36419e3301339"
integrity sha512-NAnt2iGDXohE5LI7uBnLnqvLQMtzhkiAOLXTmv+qnF9Ky7xAPcX8Up/xWIhxvLVGJvuLiNc4xQLtuqDRzb4fSA==

react-redux@^7.2.2:
version "7.2.2"
resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-7.2.2.tgz#03862e803a30b6b9ef8582dadcc810947f74b736"
integrity sha512-8+CQ1EvIVFkYL/vu6Olo7JFLWop1qRUeb46sGtIMDCSpgwPQq8fPLpirIB0iTqFe9XYEFPHssdX8/UwN6pAkEA==
dependencies:
"@babel/runtime" "^7.12.1"
hoist-non-react-statics "^3.3.2"
loose-envify "^1.4.0"
prop-types "^15.7.2"
react-is "^16.13.1"

react-refresh@^0.8.3:
version "0.8.3"
resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.8.3.tgz#721d4657672d400c5e3c75d063c4a85fb2d5d68f"
Expand Down Expand Up @@ -9990,6 +10001,14 @@ redent@^3.0.0:
indent-string "^4.0.0"
strip-indent "^3.0.0"

redux@^4.0.5:
version "4.0.5"
resolved "https://registry.yarnpkg.com/redux/-/redux-4.0.5.tgz#4db5de5816e17891de8a80c424232d06f051d93f"
integrity sha512-VSz1uMAH24DM6MF72vcojpYPtrTUu3ByVWfPL1nPfVRb5mZVTve5GnNCUV53QM/BZ66xfWrm0CTWoM+Xlz8V1w==
dependencies:
loose-envify "^1.4.0"
symbol-observable "^1.2.0"

regenerate-unicode-properties@^8.2.0:
version "8.2.0"
resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-8.2.0.tgz#e5de7111d655e7ba60c057dbe9ff37c87e65cdec"
Expand Down Expand Up @@ -11208,7 +11227,7 @@ svgo@^1.0.0, svgo@^1.2.2:
unquote "~1.1.1"
util.promisify "~1.0.0"

[email protected]:
[email protected], symbol-observable@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.2.0.tgz#c22688aed4eab3cdc2dfeacbb561660560a00804"
integrity sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==
Expand Down

0 comments on commit f730084

Please sign in to comment.