I recently took on a 45-minute Wordle challenge. The goal? Build the popular Wordle game using React in just 45 minutes. ⏱️
For anyone who hasn’t played, Wordle is a word puzzle game. You get six tries to guess a five-letter word. After each guess, you get feedback: green for the right letter in the right spot, yellow for the right letter in the wrong spot, and gray for letters not in the word at all.
Inspiration
This challenge idea came from Conner Ardman and Clément Mihailescu, who did a similar React coding challenge. You can check out their full video here.
Recording
I’m not a pro content creator, so I recorded a sped-up version of my coding process. It’s not the most polished, but I hope it’s interesting.
Getting Started
First, I set up a new project using Next.js instead of React. Next.js is a great starter because it comes with the setup done. To start a new Next.js project, use this command:
yarn create next-app
With my project ready, I started coding and set a timer. Here’s how it went.
Setting Up the Game State
My first step was to set up the game’s state. I used the useState hook to manage:
- The word to guess
- The player’s current guess
- The guesses they made so far
I also used the useEffect
hook to pick a random word from a list stored in a JSON file. I found this list on GitHub and converted it to a JavaScript array using arrayThis.
const Wordle = () => {
const [solution, setSolution] = useState('')
const [currentGuess, setCurrentGuess] = useState('')
const [isGameOver, setIsGameOver] = useState(false)
const [guesses, setGuesses] = useState<(string | null)[]>(
Array.from({ length: 6 }).fill(null) as (string | null)[]
)
const fetchNewSolution = useCallback(() => {
const wordsLength = WordsList.length
const randomIndex = Math.floor(Math.random() * wordsLength)
setSolution(WordsList[randomIndex])
}, [])
useEffect(() => {
fetchNewSolution()
}, [])
}
export default Wordle
Input Handling
Next, I needed to capture user input. I used the onkeydown
event to get each letter as it was typed. This way, I didn’t need to use an input field, keeping it simple.
const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
if (e.key === 'Enter') return handleGuess()
if (e.key === 'Backspace')
return setCurrentGuess((currentGuess) => currentGuess.slice(0, -1))
return setCurrentGuess((currentGuess) => currentGuess + e.key)
}
Implementing Feedback Logic
Now, I created the feedback logic. This compares the player’s guess to the solution and changes the colors of each letter to show if it’s correct.
const handleGuess = () => {
const currentGuessLowerCase = currentGuess.toLowerCase()
const solutionLowerCase = solution.toLowerCase()
if (currentGuessLowerCase.length !== 5) return
if (guesses.length === 6) return setIsGameOver(true)
const isSolution = solutionLowerCase === currentGuessLowerCase
if (isSolution) {
setIsGameOver(true)
return
}
setGuesses((guesses) => [
...guesses.slice(0, currentGuess.length),
isSolution ? null : currentGuess,
])
}
Rendering the Game
With the main logic done, it was time to create the UI. I made a simple UI to show the player’s guesses and feedback.
return (
<div className="h-screen w-screen flex flex-col items-center justify-center gap-8">
<h1 className="text-3xl font-medium">Wordle</h1>
<div className="flex flex-col items-center gap-y-4">
{guesses.map((guess, index) => (
<Guess
guess={currentGuessIndex === index ? currentGuess : guess ?? ''}
solution={solution}
isStillGuessing={currentGuessIndex === index}
key={index}
/>
))}
</div>
<AnimatePresence mode="wait">
{isGameOver && (
<motion.div
className="fixed inset-0 z-50 bg-gray-100/50 flex items-center justify-center"
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
transition={{ duration: 0.5, ease: 'easeInOut' }}
>
<GameOver
isWinner={guesses[currentGuessIndex - 1] === solution}
rounds={currentGuessIndex}
solution={solution}
onPlayAgain={onPlayAgain}
/>
</motion.div>
)}
</AnimatePresence>
</div>
)
And the Guess
component:
const Guess = ({ isStillGuessing, guess, solution }: GuessesProps) => {
const arr = Array(5).fill('')
for (let i = 0; i < guess.length; i++) {
arr[i] = guess[i]
}
return (
<div className="grid grid-cols-5 gap-x-2">
{arr.map((char, index) => {
const isColored = !isStillGuessing && char !== ''
const isGreen = isColored && solution.charAt(index) === char
const isYellow = isColored && !isGreen && solution.includes(char)
const isGray = isColored && !isGreen && !isYellow
return (
<div
className={cn(
'w-14 h-14 border border-gray-200 rounded flex items-center justify-center text-2xl',
{
'bg-green-400': isGreen,
'bg-yellow-400': isYellow,
'bg-gray-200': isGray,
}
)}
key={index}
>
{char}
</div>
)
})}
</div>
)
}
Final Thoughts
Completing a Wordle game in React within 45 minutes was a fun and intense challenge. While there's always room for improvements, like polishing the design, this project was a great way to practice coding under time pressure.
If you enjoy fast-paced coding, challenges like this one are a perfect way to boost your skills and creativity. I’d love to hear your thoughts or see your own versions—feel free to reach out on social media or by email!