# JS 的奇幻旅程 <br> ## Tic-Tac-Toe [TOC] ---- Made by FanRende (030Mortal#5525) <img src="https://i.imgur.com/ApP0azJ.png" width="50%"> --- ## Tutorial 基本上是跟著這個教學走 [Tutorial: Tic-Tac-Toe *React](https://beta.reactjs.org/learn/tutorial-tic-tac-toe) ---- ### 開發環境 在 Arch Linux 的一個 distribution Manjaro 上開發 Local 時使用 VSCode 及 terminal Remote 時使用 [Code Server](https://github.com/coder/code-server) 搭配 ssh forward local port ---- ### Build Tool 使用了之前介紹的 Vite 來作為 Module Bundler ---- ### 結果 <img src="https://i.imgur.com/7hbyZei.png" width="75%"> --- ## React.JS 基本概念 - Component & Props - JSX - State ---- ### Component & Props 將一整個 UI 切分成很多塊 Component 並且每個 Component 可能還有自己的子 Component <div class="flex-container"> <div class="flex-content"> <img src="https://i.imgur.com/jMCbmTP.png" width="100%"> </div> <div class="flex-content" style="font-size: 0.5em"> 1. **FilterableProductTable (grey)** contains the entire app. 1. **SearchBar (blue)** receives the user input. 1. **ProductTable (lavender)** displays and filters the list according to the user input. 1. **ProductCategoryRow (green)** displays a heading for each category. 1. **ProductRow (yellow)** displays a row for each product. </div> </div> ---- ### JSX `Square` Component in Tic-Tac-Toe ```jsx function Square({ value, onSquareClick }) { return ( <button className="square" onClick={onSquareClick}> {value} </button> ); } ``` ---- #### Conditional Rendering 利用 Javascript 的流程控制 控制組件渲染的時機 ```jsx function AdminPanel({ isAdmin }) { if(!isAdmin) return; return <span>Admin</span>; } ``` ---- ### State 如果一個參數需要在多個元件間共用 React 中可以使用 state ```jsx import { useState } from 'react'; function IndexPanel() { const [index, setIndex] = useState(0); function handleClick() { setIndex(index + 1); } return <button onclick={handleClick}>{index}</button> } ``` ---- #### Proper props for set state ```jsx import { useState } from 'react'; function IndexButton({index, onIndexChange}) { return <button onclick={onIndexChange}>next</button> } function IndexPanel() { const [index, setIndex] = useState(0); function handleClick() { setIndex(index + 1); } return ( <> <IndexButton index={index} onIndexChange={handleClick} /> <span>{index}</span> </> ); } ``` </div> </div> ---- #### simply replace state may cause problems React update state during next render before the render, state value is the same <div class="flex-container"> <div class="flex-content"> e.g. </div> <div class="flex-content"> ```jsx import { useState } from 'react'; export default function Counter() { const [number, setNumber] = useState(0); return ( <> <h1>{number}</h1> <button onClick={() => { setNumber(number + 1); setNumber(number + 1); setNumber(number + 1); }}>+3</button> </> ) } ``` </div> <div class="flex-content"> ```javascript // frame 0 "number is 0" setNumber(0 + 1); setNumber(0 + 1); setNumber(0 + 1); // frame 1 "number becomes 1" "number becomes 1" "number becomes 1" ``` </div> </div> ---- you should use an **updater function** to update state <div class="flex-container"> <div class="flex-content"> ```jsx import { useState } from 'react'; export default function Counter() { const [number, setNumber] = useState(0); return ( <> <h1>{number}</h1> <button onClick={() => { setNumber(number => number + 1); setNumber(number => number + 1); setNumber(number => number + 1); }}>+3</button> </> ) } ``` </div> <div class="flex-content"> ```jsx // frame 0 "number is 0" setNumber(number => number + 1); setNumber(number => number + 1); setNumber(number => number + 1); // frame 1 "number becomes number + 1 = 1" "number becomes number + 1 = 2" "number becomes number + 1 = 3" ``` </div> </div> --- 參考 / 延伸閱讀: - [React Docs BETA](https://beta.reactjs.org/) <style> .gray { color: gray; font-size: 0.5em; } .json, .jsx { font-size: 0.75em !important; line-height: 1.2em !important; } .mermaid { background-color: rgba(0, 0, 0, 0) !important; } .flex-container { display: flex; justify-content: center; } .flex-content { flex-grow: 1; } </style> <style> /* Customize website's scrollbar like Mac OS */ ::-webkit-scrollbar { -webkit-appearance: none; width: 7px; } ::-webkit-scrollbar-thumb { border-radius: 4px; background-color: rgba(128, 128, 128, 1); -webkit-box-shadow: 0 0 1px rgba(255, 255, 255, .5); } </style>
{"metaMigratedAt":"2023-06-17T19:25:23.397Z","metaMigratedFrom":"YAML","title":"JS 的奇幻旅程 Tic-Tac-Toe","breaks":true,"description":"Tic-Tac-Toe in ReactJS Tutorial","slideOptions":"{\"theme\":\"solarized\",\"transition\":\"fade\",\"previewLinks\":true}","contributors":"[{\"id\":\"82f6b599-31b8-4112-9dc5-7d7b7d6a3ebb\",\"add\":6900,\"del\":1986}]"}
    450 views
   Owned this note