Tools
React Explained Through a Tic-Tac-Toe Build
2025-12-29
0 views
admin
What Is React? ## How React Works ## React in the MVC Model ## Virtual DOM & One-Way Data Flow ## Prerequisites Before Learning React ## Components in React ## Working With State ## React Hooks (Overview) ## Creating a React App React is a library for building user interfaces. It runs in the browser as a Single Page Application (SPA), but it’s often used as part of a full-stack setup where it communicates with a server or API. It’s sometimes referred to as a framework because it’s powerful and comparable to Angular or Vue—but technically, React focuses on the view layer. A React app is typically a single HTML page. React doesn’t include routing out of the box—most projects use react-router-dom. In an MVC architecture: React acts as the View. Instead of separating logic and markup, React uses JSX, which allows JavaScript and markup to live together in a readable way. React uses a Virtual DOM, allowing it to: State is immutable—you don’t change it directly.
You replace it using functions like setState() or useState(). You should be comfortable with: React isn’t hard—but it assumes JavaScript fluency. React UIs are built from components. Modern React primarily uses function components with Hooks. Class components still exist, but they’re now considered legacy. State controls how components behave and render. State is always updated immutably. Two common approaches: Templates let you quickly answer FAQs or store snippets for re-use. Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment's permalink. Hide child comments as well For further actions, you may consider blocking this person and/or reporting abuse COMMAND_BLOCK:
bash
npx create-react-app my-app or with Vite: npx create-vite@latest my-app -- --template react Both provide: a preconfigured dev environment React + tooling a structured project layout Basic File Structure public/index.html → mounts the app via <div id="root"></div> src/index.js → entry point App.js → root component JSX must return a single root element (or use fragments <> </>). JSX vs Jinja Both mix logic with markup: JSX runs client-side Jinja runs server-side They solve similar problems at different layers. Props & Component Communication Props are passed from parent to child. You can: pass individual values destructure props pass functions for event handling Props make components reusable and predictable. Styling in React Common options: inline styles external CSS files reusable styled components Remember: use className, not class Lists, Keys, and Immutability When rendering lists: each item needs a unique key state updates must be immutable Instead of mutating arrays: setItems([...items, newItem]) Global State Options For shared state: Context API Redux other state managers Choose based on complexity—not hype. Production Builds To build for production: npm run build This: bundles JavaScript minifies assets removes development-only code outputs optimized files into /build That folder is what gets deployed. Applying These Concepts: Building Tic-Tac-Toe
Multidimensional Arrays in JavaScript A Tic-Tac-Toe board is a 3×3 grid, represented as an array of arrays. This structure works well for: Tic-Tac-Toe boards Chess boards Seating charts Tables of data Maps Each sub-array is a row. Each item is a cell. Managing Game State with Immutability Objects and arrays are reference values in JavaScript. You should never mutate them directly. Instead: create a copy update the copy replace the state React only re-renders when it sees a new reference. Lifting State Up Lifting state up means moving shared state to the closest common parent. You do this when: multiple components need the same data one updates the state and another reads it This keeps everything in sync. Lifting State in Tic-Tac-Toe In this project: <GameBoard /> renders the grid <Player /> shows whose turn it is Both need to know the active player. Solution Keep activePlayer in <App /> and pass it down as props. Key ideas: state lives in the parent children receive it via props children request updates via callbacks Avoiding Intersecting State Intersecting state happens when the same data exists in multiple places. This causes: unpredictable behavior debugging headaches Best practice: keep a single source of truth derive state when possible Deriving State Instead of Storing It The game board itself does not use useState. Instead: it receives turns as props it replays those turns to reconstruct the board This makes the board: stateless predictable easier to reason about Determining the Winner Each cell is accessed using: board[row][col] There are 8 winning combinations: 3 rows 3 columns 2 diagonals Loop through each and check if all three cells match. JSX Fragment Gotcha This causes an error: {winner && <GameOver /><p>Winner: {winner}</p>} JSX expressions must return one parent element. Wrap them in a fragment or container to fix it. Two Ways to Create the Board Dynamic: Array(3).fill(null).map(() => Array(3).fill(null)) Static: [ [null, null, null], [null, null, null], [null, null, null]
] Both work—just understand reference behavior. Why Immutability Matters Mutation: arr.push(4) ❌ Same reference → React may not re-render Immutable update: const newArr = [...arr, 4] ✅ New reference → React updates correctly A Personal Reflection I compared myself to someone finishing a FastAPI course in under a day while I struggled through React. That comparison hurt. But React demands a new way of thinking: JavaScript is weirder than Python frontend is messier state management changes how you reason And Tic-Tac-Toe?
It’s deceptively complex. Finishing the Game I finished it. And more importantly: I understand React better I understand my limits better I understand my growth better A simple 3×3 grid taught me a lot. Final Thoughts React doesn’t carry you—you carry it. And that’s what makes learning it valuable. On to the next. Enter fullscreen mode Exit fullscreen mode COMMAND_BLOCK:
bash
npx create-react-app my-app or with Vite: npx create-vite@latest my-app -- --template react Both provide: a preconfigured dev environment React + tooling a structured project layout Basic File Structure public/index.html → mounts the app via <div id="root"></div> src/index.js → entry point App.js → root component JSX must return a single root element (or use fragments <> </>). JSX vs Jinja Both mix logic with markup: JSX runs client-side Jinja runs server-side They solve similar problems at different layers. Props & Component Communication Props are passed from parent to child. You can: pass individual values destructure props pass functions for event handling Props make components reusable and predictable. Styling in React Common options: inline styles external CSS files reusable styled components Remember: use className, not class Lists, Keys, and Immutability When rendering lists: each item needs a unique key state updates must be immutable Instead of mutating arrays: setItems([...items, newItem]) Global State Options For shared state: Context API Redux other state managers Choose based on complexity—not hype. Production Builds To build for production: npm run build This: bundles JavaScript minifies assets removes development-only code outputs optimized files into /build That folder is what gets deployed. Applying These Concepts: Building Tic-Tac-Toe
Multidimensional Arrays in JavaScript A Tic-Tac-Toe board is a 3×3 grid, represented as an array of arrays. This structure works well for: Tic-Tac-Toe boards Chess boards Seating charts Tables of data Maps Each sub-array is a row. Each item is a cell. Managing Game State with Immutability Objects and arrays are reference values in JavaScript. You should never mutate them directly. Instead: create a copy update the copy replace the state React only re-renders when it sees a new reference. Lifting State Up Lifting state up means moving shared state to the closest common parent. You do this when: multiple components need the same data one updates the state and another reads it This keeps everything in sync. Lifting State in Tic-Tac-Toe In this project: <GameBoard /> renders the grid <Player /> shows whose turn it is Both need to know the active player. Solution Keep activePlayer in <App /> and pass it down as props. Key ideas: state lives in the parent children receive it via props children request updates via callbacks Avoiding Intersecting State Intersecting state happens when the same data exists in multiple places. This causes: unpredictable behavior debugging headaches Best practice: keep a single source of truth derive state when possible Deriving State Instead of Storing It The game board itself does not use useState. Instead: it receives turns as props it replays those turns to reconstruct the board This makes the board: stateless predictable easier to reason about Determining the Winner Each cell is accessed using: board[row][col] There are 8 winning combinations: 3 rows 3 columns 2 diagonals Loop through each and check if all three cells match. JSX Fragment Gotcha This causes an error: {winner && <GameOver /><p>Winner: {winner}</p>} JSX expressions must return one parent element. Wrap them in a fragment or container to fix it. Two Ways to Create the Board Dynamic: Array(3).fill(null).map(() => Array(3).fill(null)) Static: [ [null, null, null], [null, null, null], [null, null, null]
] Both work—just understand reference behavior. Why Immutability Matters Mutation: arr.push(4) ❌ Same reference → React may not re-render Immutable update: const newArr = [...arr, 4] ✅ New reference → React updates correctly A Personal Reflection I compared myself to someone finishing a FastAPI course in under a day while I struggled through React. That comparison hurt. But React demands a new way of thinking: JavaScript is weirder than Python frontend is messier state management changes how you reason And Tic-Tac-Toe?
It’s deceptively complex. Finishing the Game I finished it. And more importantly: I understand React better I understand my limits better I understand my growth better A simple 3×3 grid taught me a lot. Final Thoughts React doesn’t carry you—you carry it. And that’s what makes learning it valuable. On to the next. COMMAND_BLOCK:
bash
npx create-react-app my-app or with Vite: npx create-vite@latest my-app -- --template react Both provide: a preconfigured dev environment React + tooling a structured project layout Basic File Structure public/index.html → mounts the app via <div id="root"></div> src/index.js → entry point App.js → root component JSX must return a single root element (or use fragments <> </>). JSX vs Jinja Both mix logic with markup: JSX runs client-side Jinja runs server-side They solve similar problems at different layers. Props & Component Communication Props are passed from parent to child. You can: pass individual values destructure props pass functions for event handling Props make components reusable and predictable. Styling in React Common options: inline styles external CSS files reusable styled components Remember: use className, not class Lists, Keys, and Immutability When rendering lists: each item needs a unique key state updates must be immutable Instead of mutating arrays: setItems([...items, newItem]) Global State Options For shared state: Context API Redux other state managers Choose based on complexity—not hype. Production Builds To build for production: npm run build This: bundles JavaScript minifies assets removes development-only code outputs optimized files into /build That folder is what gets deployed. Applying These Concepts: Building Tic-Tac-Toe
Multidimensional Arrays in JavaScript A Tic-Tac-Toe board is a 3×3 grid, represented as an array of arrays. This structure works well for: Tic-Tac-Toe boards Chess boards Seating charts Tables of data Maps Each sub-array is a row. Each item is a cell. Managing Game State with Immutability Objects and arrays are reference values in JavaScript. You should never mutate them directly. Instead: create a copy update the copy replace the state React only re-renders when it sees a new reference. Lifting State Up Lifting state up means moving shared state to the closest common parent. You do this when: multiple components need the same data one updates the state and another reads it This keeps everything in sync. Lifting State in Tic-Tac-Toe In this project: <GameBoard /> renders the grid <Player /> shows whose turn it is Both need to know the active player. Solution Keep activePlayer in <App /> and pass it down as props. Key ideas: state lives in the parent children receive it via props children request updates via callbacks Avoiding Intersecting State Intersecting state happens when the same data exists in multiple places. This causes: unpredictable behavior debugging headaches Best practice: keep a single source of truth derive state when possible Deriving State Instead of Storing It The game board itself does not use useState. Instead: it receives turns as props it replays those turns to reconstruct the board This makes the board: stateless predictable easier to reason about Determining the Winner Each cell is accessed using: board[row][col] There are 8 winning combinations: 3 rows 3 columns 2 diagonals Loop through each and check if all three cells match. JSX Fragment Gotcha This causes an error: {winner && <GameOver /><p>Winner: {winner}</p>} JSX expressions must return one parent element. Wrap them in a fragment or container to fix it. Two Ways to Create the Board Dynamic: Array(3).fill(null).map(() => Array(3).fill(null)) Static: [ [null, null, null], [null, null, null], [null, null, null]
] Both work—just understand reference behavior. Why Immutability Matters Mutation: arr.push(4) ❌ Same reference → React may not re-render Immutable update: const newArr = [...arr, 4] ✅ New reference → React updates correctly A Personal Reflection I compared myself to someone finishing a FastAPI course in under a day while I struggled through React. That comparison hurt. But React demands a new way of thinking: JavaScript is weirder than Python frontend is messier state management changes how you reason And Tic-Tac-Toe?
It’s deceptively complex. Finishing the Game I finished it. And more importantly: I understand React better I understand my limits better I understand my growth better A simple 3×3 grid taught me a lot. Final Thoughts React doesn’t carry you—you carry it. And that’s what makes learning it valuable. On to the next. - Created and maintained by Facebook
- Runs in the browser
- Compiles into a JavaScript bundle loaded once
- Handles routing and updates client-side
- Commonly paired with backend frameworks like Django - mounts into a root <div>
- manages routing internally
- updates only the parts of the UI that change
- communicates with the server using JSON - UPDATE data
- DELETE data - Model → data
- Controller → routing & requests - update parts of the page without full reloads
- remain fast and responsive - UI events → state updates - debugging easier
- performance more predictable - JavaScript fundamentals
- variables, functions, arrays, objects
- async/await & Promises
- array methods like .map() and .forEach()
- Fetch API & HTTP concepts - are reusable
- manage their own state
- compose together like puzzle pieces - Local state → belongs to one component
- Global state → shared across components - useState → manage state
- useEffect → handle side effects
how-totutorialguidedev.toaimlserverbashroutingrouterpythonjavascript