Playing with React: Ugliest poker game ever — Part I

Esteban Molina Abad
Globant
Published in
6 min readAug 27, 2020

React, Redux & Sagas Poker Game Implementation

This series is focused on implementing a fully functional poker game exploring interesting and modern approaches on the Front End and open source casino server on the back end.

In this article we’ll analyze visual designs, set up an initial architecture, navigation and presentational components using React, Styled Components, Function Components and follow some ground rules like Unit Test with Jest & Enzyme, Airbnb Lint Style Guide and Conventional Commits.

Feel free to follow the step by step commits here and find all the images here.

Project Setup

Now let’s create our react.js project using Create React App (CRA)

npx create-react-app uglyest-poker-game-ever

Install all the tools we need for a healthy project

npm install react-i18next react-router-dom styled-components eslint prettier jest eslint-plugin-jest babel-jest jest-styled-components enzyme enzyme-adapter-react-16 enzyme-to-json husky @commitlint/cli @commitlint/config-conventional — save-dev

Check the configuration in the package.json file.

npm run start

You should get the default screen generated by CRA on the browser,

Fig 1

At this point your code base should look like this:

Following the conventional commits we’ll use the commit type ‘chore’ and the scope ‘setup’:

git commit -m “feat(setup): project initial setup”

And that’s our first commit

Introducing Visuals

Fig 2

Fig 3

Fig 4

Fig 5

Let’s think about the actual architecture. Checking the visuals we can infer 4 different pages (login, register, lobby and game room), so it’s a small app and we can manage it using a function-first approach. And if you want to scale, you can always Go Ducks!.

For this article’s purposes, we’ll focus on the presentational layer and set up the navigation so we can start working from there. So first, lets define routes for each one of the identified screens:

import React, { Component } from ‘react’;import {
BrowserRouter as Router,
Switch,
Route
} from ‘react-router-dom’;
import Lobby from ‘./Lobby’;
import Login from ‘./Login’;
import Register from ‘./Register’;
import Room from ‘./Room’;
const App = () => (
<Router>
<Switch>
<Route exact path=”/” component={Login} />
<Route path=”/login” component={Login} />
<Route path=”/lobby” component={Lobby} />
<Route path=”/register” component={Register} />
<Route path=”/room/:id?” component={Room} />
</Switch>
</Router>
);
export default App;

containers/App.js

And some empty components meant to be containers:

And that’s our second commit

Dumb Components

Checking the visuals again you will note different components (buttons, panels, inputs, avatars, cards …) which at same time will compose the containers. We want those implemented as soon as possible.

Background

First of all, a shared element across all the screen is the background which is composed by a circular gradient (Indigo to Blackcurrant) and a pattern. In the spirit of keep it DRY, we’re going to define our Theme component which will provide access to all the color, font and size variables and Background component which would use that gradient and the “bkg_patternimage:

import React from “react”;
import { ThemeProvider } from “styled-components”;
const theme = {
colors: {
indigo: “#4A0968”,
blackcurrant: “#27172F”,
}
};
const Theme = ({ children }) => (
<ThemeProvider theme={theme}>{children}</ThemeProvider>
);
export default Theme;

Theme.js

In order to make theme variables available for all the components we have to include in the root component a wrap with all the children:

const App = () => (
<Theme>
<Background>
<Router>
<Switch>
<Route exact path=”/” component={Login} />
<Route path=”/login” component={Login} />
<Route path=”/lobby” component={Lobby} />
<Route path=”/register” component={Register} />
<Route path=”/room/:id?” component={Room} />
</Switch>
</Router>
</Background>
</Theme>
);

containers/App.js

As you can notice Background is already inside the Theme component so we can consume theme variables inside the styled components definitions.

                ${props => props.theme.colors.indigo}
import styled from ‘styled-components’;const Background = styled.section`
align-items: center;
background: ${props => props.theme.colors.indigo};
background: ${props => `radial-gradient(
circle, ${props.theme.colors.indigo} 11%, ${props.theme.colors.blackcurrant} 64%)`};
display: flex;
flex-direction:column;
justify-content: center;
height: 100vh;
width: 100%;
&:before {
background: url(/img/bkg_pattern.png) repeat;
background-size: contain;
content: ‘’;
height: 100%;
left: 0;
position: absolute;
top: 0;
width: 100%;
z-index: 0;
}`;
export default Background;

components/Background.js

At this point, your poker game should look like a super nice casino wallpaper:

Fig 6

And that’s our third commit.

Button, Input and Link

We are going to style these 3 basic components using some theme variable and a really powerful extension mechanism from styled components. In this particular case we’re extending Link component from react-dom-router with a really simple function ‘styled(Link)’ :

import styled from ‘styled-components’;
import { Link } from ‘react-router-dom’;
const MyLink = styled(Link)`
align-self: center;
color: ${props => props.theme.colors.pineTree};
cursor: pointer;
font-weight: bold;
margin: 10px 0;
`;
export default MyLink;

components/MyLink.js

import styled from ‘styled-components’;const Button = styled.button`
align-self: center;
border: 2px solid ${props => props.theme.colors.bahia};
border-radius: 8px;
background: ${props => props.theme.colors.bahiaGradient};
color: ${props => props.theme.colors.pineTree};
cursor: pointer;
font-weight: bold;
margin: 10px 0;
outline: none;
padding: 5px 30px;
`;
export default Button;

components/Button.js

import styled from ‘styled-components’;
const Input = styled.input`
background: ${props => props.theme.colors.limeade};
border: none;
color: ${props => props.theme.colors.pineTree};
width: 100%;
text-align: center;
padding: 4px;
margin:8px 0;
outline: none;
font-weight: bold;
::placeholder{
color: ${props => props.theme.colors.pineTree};
font-weight: bold;
}
`;
export default Input;

components/Input.js

Panel

Login and Registry sections share a little panel with the ‘christi’ background and the ‘milanoRed’ border:

import React from ‘react’;
import styled from ‘styled-components’;
const PanelWrapper = styled.section`
background: ${props => props.theme.colors.milanoRed};
border-radius: 8px;
max-width: 480px;
padding: 15px;
position: relative;
width: 80%;
z-index: 2;
`;
const PanelContent = styled.section`
background: ${props => props.theme.colors.christi};
border-radius: 8px;
display: flex;
justify-content: center;
padding: 20px;
flex-direction: column;
`;
const ChipsImage = styled.img`
position: absolute;
bottom: -20px;
left: -20px;
width:20%;
`;
const Panel = ({children}) => (
<PanelWrapper>
<PanelContent>
{children}
</PanelContent>
<ChipsImage src=”/img/coins.png”></ChipsImage>
</PanelWrapper>
);
export default Panel;

components/Panel.js

Let’s Implement Containers

Login and registry are really similar, it’s the panel, some inputs and buttons, so here goes the code for one of them. You can always check the other one in the repo.

import React from ‘react’;
import { Button, Input, MyLink, Panel } from ‘../components’;
const Login = () => (
<Panel>
<Input
placeholder=”Nombre de usuario”
name=”uid”></Input>
<Input placeholder=”Contraseña”
name=”passwd”></Input>
<Button>Ingresar</Button> <MyLink to=”/register”>No estas registrado?</MyLink></Panel>
);
export default Login;

components/Login.js

By now you should get something like Fig 2

Last but not Least, Tests

Since we went with a function-first approach for the file structure, all test files should go on __tests__ folders (Fig 7). For our app they are present at Components and Containers folders and we will be writing snapshot tests which are really simple. But for styled components there is a trick though, we have to pass the theme as a prop:

import React from ‘react’;
import { shallow } from ‘enzyme’;
import ‘jest-styled-components’
import Button from ‘../Button’;
import { theme } from ‘../../Theme’;
describe(‘Button Component’, () => {
it(‘should render correctly’, () => {
const component = shallow(<Button theme={theme}/>);
expect(component).toMatchSnapshot();
});
});

components/__tests__/Button.test.js

Fig 7

And that’s our fourth commit.

With that last commit we close the first article of the series. For Part II we’re going to implement the lobby and game room views. We’ve just scratched the surface for react and styled components capabilities. I really hope you have enjoyed it and follow the series.

--

--