How to Build “Wordle” Using ReactJS and About 200 Lines of Sloppy Code

It’s easier than you may think

Step 1: Imagine the App

I even lose at game I wrote myself

Step 2: Build the App

npx create-react-app Wordle
A ReactJS App Framework

Step 3: Code the App

this.state = {words:[],board:[[{letter:"",status:"white"},{letter:"",status:"white"},{letter:"",status:"white"},{letter:"",status:"white"},{letter:"",status:"white"}],[{letter:"",status:"white"},{letter:"",status:"white"},{letter:"",status:"white"},{letter:"",status:"white"},{letter:"",status:"white"}],[{letter:"",status:"white"},{letter:"",status:"white"},{letter:"",status:"white"},{letter:"",status:"white"},{letter:"",status:"white"}],[{letter:"",status:"white"},{letter:"",status:"white"},{letter:"",status:"white"},{letter:"",status:"white"},{letter:"",status:"white"}],[{letter:"",status:"white"},{letter:"",status:"white"},{letter:"",status:"white"},{letter:"",status:"white"},{letter:"",status:"white"}],[{letter:"",status:"white"},{letter:"",status:"white"},{letter:"",status:"white"},{letter:"",status:"white"},{letter:"",status:"white"}]],currentRow:0,currentWord: '',currentGuess: '',errorMessage: String.fromCharCode(160),gameOver: false};}
String.fromCharCode(160)
If that was usually blank, everything would move around when there were words there.
async downloadDictionary() {let response = await fetch("5LetterWords.txt");if(response.status !== 200) {throw new Error("Server Error");}// read response stream as textlet text_data = await response.text();let wordList = text_data.split("\n");let maxWords = wordList.length;let wordNumber = getRandomInt(0,maxWords);this.setState({words: wordList,currentWord:wordList[wordNumber].toUpperCase()});}
let wordList = text_data.split("\n");
let maxWords = wordList.length;let wordNumber = getRandomInt(0,maxWords);
function getRandomInt(min, max) {min = Math.ceil(min);max = Math.floor(max);return Math.floor(Math.random() * (max - min + 1)) + min;}
this.setState({words: wordList,currentWord:wordList[wordNumber].toUpperCase()});
componentDidMount = () => {this.downloadDictionary();}
render(){console.log(this.state.currentWord);return (<div className="App"><header className="App-header"><Header errorMessage={this.state.errorMessage}/><div style={{width:'180px'}}>{this.state.board.map((board,idx)=>{return (<div key = {idx}>{board.map((row,idx)=>{return(<div><Tile letter={row.letter} color={row.status} key={idx}/></div>)})}</div>)})}</div><input type="text" id="guessWordBox" value={this.state.currentGuess} maxlength="5" className='inputBox' /><Keyboard keyboardType={this.keyboardType} /></header></div>);}
<div className="App"><header className="App-header">
We haven’t added Keyboard or Tile yet, but we will
import React, { Component } from 'react';class Header extends Component {render() {return (<div><div style={{fontSize:'2.5em'}}> 🆆 🅾 🆁 🅳 🅻 🅴 🆁 <br/></div><div style={{color:'red'}}>{this.props.errorMessage}</div></div>)}}export default Header;
<Header errorMessage={this.state.errorMessage}/>
{this.state.board.map((board,idx)=>{return (<div key = {idx}>{board.map((row,idx)=>{return(<div><Tile letter={row.letter} color={row.status} key={idx}/></div>)})}
import React, { Component } from 'react';class Tile extends Component {render() {let bgStyle= {width:'30px',backgroundColor:this.props.color,height:'30px',fontSize:'x-large',float:'left',border:'1px solid white',marginRight:'4px',marginTop:'4px',paddingBottom:'4px',color:"black",borderRadius:'5px',verticalAlign:'middle'}return (<div style={bgStyle}>{this.props.letter}</div>)}}export default Tile;
<Tile letter={row.letter} color={row.status} key={idx}/>
<input type="text" id="guessWordBox" value={this.state.currentGuess} maxlength="5" className='inputBox' /><Keyboard keyboardType={this.keyboardType} usedList={this.state.usedList} foundList={this.state.foundList} correctList={this.state.correctList} />
import React, { Component } from 'react';import '../App.css';class Keyboard extends Component {constructor(props) {super(props);this.state = {topRow:["Q","W","E","R","T","Y","U","I","O","P"],middleRow:["A","S","D","F","G","H","J","K","L"],bottomRow:["Z","X","C","V","B","N","M","←","Enter"]};}handleClick = (event) => {this.props.keyboardType(event.currentTarget.textContent);};
render() {return (<div style={{display: "flex",flexWrap:"wrap",justifyContent:"center",width:"330px",textAlign:"center"}}><div style={{display: "flex",flexWrap:"wrap",justifyContent:"center",width:"100%"}}>{this.state.topRow.map((letter,idx)=> <div className='keyStyle' key={letter} onClick={this.handleClick} >{letter}</div>)})}</div> <br/><div style={{display: "flex",flexWrap:"wrap",justifyContent:"center",width:"100%"}}>{this.state.middleRow.map((letter,idx)=> {return(<div className='keyStyle' key={letter} onClick={this.handleClick} >{letter}</div>)})}</div><br/><div style={{display: "flex",flexWrap:"wrap",justifyContent:"center",width:"100%"}}>{this.state.bottomRow.map((letter,idx)=> <div className='keyStyle' key={letter} onClick={this.handleClick} >{letter}</div>)})}</div></div>)}}export default Keyboard;
this.state = {topRow:["Q","W","E","R","T","Y","U","I","O","P"],middleRow:["A","S","D","F","G","H","J","K","L"],bottomRow:["Z","X","C","V","B","N","M","←","Enter"]};}
handleClick = (event) => {this.props.keyboardType(event.currentTarget.textContent);};
<Keyboard keyboardType={this.keyboardType} } />
{this.state.topRow.map((letter,idx)=><div className='keyStyle' key={letter} onClick={this.handleClick} >{letter}</div>)})}</div>
<Keyboard keyboardType={this.keyboardType} />
keyboardType = (keyClicked) => {this.setState({errorMessage:String.fromCharCode(160)})let errorMessage = String.fromCharCode(160);let currentGuess= '';let guessBox = document.getElementById("guessWordBox");if(guessBox) {if(keyClicked==="Enter" && guessBox.value.length>=5){this.submitWord(guessBox.value);} else {if(guessBox.value.length<=5){if(keyClicked==="←"){guessBox.value = guessBox.value.substring(0, guessBox.value.length - 1);currentGuess=guessBox.value;}elseguessBox.value+=keyClicked;currentGuess=guessBox.value;}else {errorMessage="We're only looking for 5-digit words";currentGuess=''this.setState({errorMessage:errorMessage})}}}
keyboardType = (keyClicked) => {
this.setState({errorMessage:String.fromCharCode(160)})
let errorMessage = String.fromCharCode(160);let currentGuess= '';
let guessBox = document.getElementById("guessWordBox");if(guessBox) {
if(keyClicked==="Enter" && guessBox.value.length>=5){this.submitWord(guessBox.value);}
else {if(guessBox.value.length<=5){if(keyClicked==="←"){guessBox.value = guessBox.value.substring(0, guessBox.value.length - 1);currentGuess=guessBox.value;}
else {errorMessage="We're only looking for 5-digit words";currentGuess=''this.setState({errorMessage:errorMessage})}
submitWord = (wordSubmitted) => {if(!this.state.gameOver){if (this.checkword(wordSubmitted)){let currentBoard = [...this.state.board];let currentWord = this.state.currentWord;let boardRow = this.state.currentRow;let errorMessage= this.state.errorMessage;let tileColor="white";let newRow = [];for(let i =0; i<wordSubmitted.length;i++){if(currentWord.includes(wordSubmitted[i])){tileColor="blue";if(currentWord[i]===wordSubmitted[i]){tileColor="lightgreen";}}newRow[i]={letter: wordSubmitted[i],status: tileColor}tileColor="white";}currentBoard[boardRow]=newRow;boardRow++;let gameOver = falseif(boardRow>5) {gameOver=true;errorMessage="Bad Luck. The word was "+ currentWord + ". Play again!";}if(wordSubmitted===currentWord){errorMessage="You WIN!"gameOver=true;}this.setState({board:currentBoard,currentRow:boardRow,gameOver:gameOver,errorMessage: errorMessage})}}}
submitWord = (wordSubmitted) => {if(!this.state.gameOver){
if (this.checkword(wordSubmitted)){
checkword = (wordToCheck) => {let wordList = this.state.words;let word = wordToCheck.toLowerCase();if (wordList.includes(word)){return(true);}else {this.setState({errorMessage:"That word is not in my dictionary"})}}
let currentBoard = [...this.state.board];let currentWord = this.state.currentWord;let boardRow = this.state.currentRow;let errorMessage= this.state.errorMessage;let tileColor="white";let newRow = [];
this.setState({variable: variable + 1;})
let tempVariable = this.state.variable + 1this.setState({variable: tempVariable})
for(let i =0; i<wordSubmitted.length;i++){if(currentWord.includes(wordSubmitted[i])){tileColor="blue";if(currentWord[i]===wordSubmitted[i]){tileColor="lightgreen";}}newRow[i]={letter: wordSubmitted[i],status: tileColor}}
currentBoard[boardRow]=newRow;boardRow++;let gameOver = false
if(boardRow>5) {gameOver=true;errorMessage="Bad Luck. The word was "+ currentWord + ". Play again!";}if(wordSubmitted===currentWord){errorMessage="You WIN!"gameOver=true;}
this.setState({board:currentBoard,currentRow:boardRow,gameOver:gameOver,errorMessage: errorMessage})}

Step 5: Upgrades, People, Upgrades

Plus, I like coffee

--

--

--

4a 75 73 74 20 61 6e 6f 74 68 65 72 20 63 6f 6d 70 75 74 65 72 20 6e 65 72 64 20 77 69 74 68 20 61 20 62 6c 6f 67

Love podcasts or audiobooks? Learn on the go with our new app.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
crashdaddy

crashdaddy

4a 75 73 74 20 61 6e 6f 74 68 65 72 20 63 6f 6d 70 75 74 65 72 20 6e 65 72 64 20 77 69 74 68 20 61 20 62 6c 6f 67

More from Medium

A React Christmas

Principles of Software development and a brief dive into Javascript

Don’t over-engineer it

How trip yourself up with React hooks and break production