Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import React, { useEffect, useState } from 'react';
- const WORD_LIST_API_URL = 'https://api.frontendexpert.io/api/fe/wordle-words';
- const WORD_LENGTH = 5;
- const NUM_ROWS = 6;
- function WordleRow({ guess, isFinal, word }) {
- function decorateGuess(guess, isFinal, word) {
- const result = [];
- for (let i = 0; i < WORD_LENGTH; i++) {
- const tile = {};
- const char = guess[i] || '';
- tile.text = char;
- tile.class = 'tile';
- // Actually assign a subclass
- if (isFinal) {
- if (word[i] === char) {
- tile.class += ' correct';
- } else if (word.includes(char)) {
- tile.class += ' close';
- } else {
- tile.class += ' incorrect';
- }
- }
- result.push(tile);
- }
- return result;
- }
- // Do not use curly braces in your arrow function o/w need explicit return
- return (
- <div className="line">
- {decorateGuess(guess, isFinal, word).map((item, index) =>
- <div key={index} className={item.class}>{item.text}</div>
- )}
- </div>
- );
- }
- export default function Wordle() {
- // Write your code here.
- // Use null so we can conditionally render a default (i.e. before the API has returned)
- const [word, setWord] = useState(null);
- const [guess, setGuess] = useState('');
- const [count, setCount] = useState(0);
- const [guesses, setGuesses] = useState([]);
- const [finished, setFinished] = useState(false);
- // Fetch the winning word on component mount.
- useEffect(() => {
- const fetchData = async () => {
- try {
- const response = await fetch(WORD_LIST_API_URL);
- const data = await response.json();
- const index = Math.floor(Math.random() * data.length);
- const winningWord = data[index];
- setWord(winningWord.toLowerCase());
- // For testing
- // setWord("hello");
- } catch (error) {
- console.error('Error fetching data:', error);
- }
- }
- fetchData();
- }, []); // Empty dependency array so it only runs once on mount.
- // Register event listener for the keypress input
- useEffect(() => {
- const handleSubmit = () => {
- if (guess.length < WORD_LENGTH || count === NUM_ROWS || finished) {
- return;
- }
- setFinished(guess === word || count === NUM_ROWS);
- setGuesses(prevGuesses => [...prevGuesses, {guess: guess, isFinal: true}]);
- setCount(prevCount => prevCount + 1);
- setGuess('');
- }
- const handleBackspace = () => {
- if (guess.length === 0 || count === NUM_ROWS || finished) {
- return;
- }
- setGuess(prevGuess => prevGuess.slice(0, -1));
- }
- const handleCharKeyPress = (char) => {
- if (guess.length === WORD_LENGTH || count === NUM_ROWS || finished) {
- return;
- }
- setGuess(prevGuess => prevGuess + char);
- }
- const handleKeyPress = (event) => {
- if (finished) return;
- if (event.key === 'Enter') {
- handleSubmit();
- } else if (event.key === 'Backspace') {
- handleBackspace();
- } else { // This is bc we don't have to expect any other input besides lowercase letters.
- handleCharKeyPress(event.key);
- }
- }
- // Very important to use window here as the test env directly dispatches events
- // to window. In a real browser, the event bubbles up from target -> document -> window
- // so it wouldn't matter if we added the listener to document or window.
- // This is why when I had document.addEventListener the code worked locally in the browser
- // but failed nearly all the unit tests.
- window.addEventListener('keydown', handleKeyPress);
- // ALSO VERY IMPORTANT TO REMOVE THE LISTENER, O/W on each re-render
- // we add a new listener so we have 2, then 3 then 4 listeners...
- return () => window.removeEventListener('keydown', handleKeyPress);
- }, [guess, count, guesses]); // VERY IMPORTANT TO SPECIFY THE CORRECT DEPS
- return (
- <div className="board">
- {word && Array.from({ length: NUM_ROWS }).map((_, i) =>
- <WordleRow
- key={i}
- guess={count === i ? guess : guesses[i]?.guess || ''}
- isFinal={count === i ? false : guesses[i]?.isFinal || false}
- word={word}/>
- )}
- </div>
- );
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement