สอนเขียนเว็บด้วย React + TypeScript ปี 2023 (Intro to React) ตอนที่ 1
สวัสดีครับ คอร์สนี้เป็นคอร์สเรียน React + TypeScript ที่ผมลองทำขึ้นมา เป้าหมายคือ เป็นเนื้อหาเบื้องต้น พื้นฐานสำหรับคนที่ไม่มีพื้นฐาน React + TypeScript มาก่อนเลย ให้สามารถทำเว็บไซต์ และ Deploy เว็บของเราได้ เนื้อหา ประมาณ 2-3 ชั่วโมง (แบบ Video) ซึ่งถ้านั่งเรียนจริงๆ + ทำ Mini Project ในคอร์สด้วย ผมว่า ใช้เวลาอย่างต่ำๆ 10 ชั่วโมงครับ
รูปแบบของ Tutorial มี 2 แบบคือ
- Video - ดูผ่าน Youtube
- Blog - เป็นบทความ อธิบายเพิ่มเติม
ทั้งสองรูปแบบใช้เนื้อหาเดียวกัน ข้อดีคือ สามารถเลือกเรียนจากรูปแบบที่ชอบได้ หรือเป็นแบบ Hybrid ก็ได้ เช่น ถ้าไม่เข้าใจเลย ก็อาจจะเริ่มจาก Video และทำตาม หรือถ้าพอมีพื้นฐาน ไม่เข้าใจแค่บางส่วน ก็อ่านบล็อกในเนื้อหาส่วนนั้นๆ เพิ่มเติมได้
0. เตรียมความพร้อม
ก่อนเริ่มเลยเนี่ย อยากให้ลองสำรวจดูความพร้อมของเรา รวมถึงเครื่องมือต่างๆ อาจจะไม่จำเป็นต้องเป๊ะๆ 100% นะครับ เป็นแค่แนวทาง อย่าง Editor หรือ Extensions ก็เป็นส่วนเสริมเท่านั้น จะลง จะใช้ ก็แล้วแต่เราเลย
มาดูสิ่งที่ต้องมี หรือต้องใช้มีอะไรบ้าง?
- VS Code - ตัว Text Editor สำหรับเขียนโค๊ด (หรือใช้ IDE/Editor ที่ชอบก็ได้)
- Node.js / NPM - ติดตั้ง Node.js และ NPM เพื่อให้สามารถติดตั้ง Library ต่างๆได้
- Terminal - มี Command Line Tool เช่น Terminal, iTerm2, Power Shell หรือสามารถใช้ built-in Terminal ที่มากับ VS Code ได้
- Prettier - เพื่อเอาไว้ format code ของเราให้เป็นแนวทางเดียวกัน (สามารถใช้ Prettier Extension VS Code ได้)
- มีความเข้าใจ HTML/CSS/JS เบื้องต้น หรือเคยเขียนเว็บไซต์มาก่อน

1. สร้างโปรเจ็ค
เราจะใช้ Vite ในการสร้างโปรเจ็ค React ขึ้นมา ซึ่ง Vite เป็น Frontend Tooling ที่ช่วยเรื่อง Config ต่างๆ ทำให้เราไม่ต้องเสียเวลาตรงนี้ เอาเวลามาโฟกัสการพัฒนาโค๊ดดีกว่า

เริ่มต้นสร้างโปรเจ็คด้วยคำสั่ง
npm create vite@latest hello-react -- --template react-ts
# หรือ เลือกจาก propmt
npm create vite@latest
เมื่อสร้างโปรเจ็คเสร็จเรียบร้อยนะครับ ต่อมาเราดูโครงสร้างภายในโปรเจ็คกันดีกว่า ว่ามีอะไรบ้าง
# tree -L 2 -I node_modules
├── index.html
├── package.json
├── public
│ └── vite.svg
├── src
│ ├── App.css
│ ├── App.tsx
│ ├── assets
│ ├── index.css
│ ├── main.tsx
│ └── vite-env.d.ts
├── tsconfig.json
├── tsconfig.node.json
└── vite.config.ts
3 directories, 11 files
src
- เป็น folder หลักที่เราจะเขียน React กันที่ folder นี้index.html
- เป็นไฟล์ html หลักของเราpackage.json
- เป็นไฟล์ที่บอกว่าโปรเจ็คเรา ชื่ออะไร มี dependecies อะไรบ้างtsconfig.json
- เป็น TypeScript config (เรายังไม่ต้องสนใจ ใช้เป็น default ก่อนครับ)
เปิดโปรเจ็คขึ้นมา ทำการสำรวจ ไฟล์และโฟลเดอร์ จากนั้นลอง start dev server ครับ
cd hello-react
# เปิดด้วย vs code
code .
# ติดตั้ง dependencies
npm install
เมื่อติดตั้ง dependencies เรียบร้อย ก็ลอง Start dev server
npm run dev

ทำการเปิดหน้าเว็บ http://localhost:5173 เราจะเห็น React ของเรา หน้าตาแบบนี้

ทดลองแก้ไขไฟล์ src/App.tsx
กดเซฟ และสังเกตหน้าเว็บ มีการเปลี่ยนแปลง โดยที่เราไม่ต้อง refresh หน้าเว็บเลย
Auto save และ Auto formatting
สำหรับคนที่ต้องการ Auto Save และ Auto Formatting โค๊ดให้เรา (บางคนชอบแก้โค๊ดแล้วลืมเซฟ) เราสามารถตั้งค่าตามนี้ได้ครับ

- Prettier - เป็น Extensions หลัก ที่ควรมีติดไว้ (ไม่ใช้ Extension ก็ขอให้มีไฟล์
.prettierrc
- ES Lint - เป็นตัวช่วยตรวจสอบโค๊ดของเรา (Optional)
มาดูที่การตั้งค่า ทั้ง 3 ค่า ที่แนะนำ คือ
- การตั้งค่า Auto Save : Settings → หาคำว่า Auto Save เลือก
onFocusChange
- การตั้งค่า Auto Formatting : Settings → ติ๊กถูก Format on Save
- การเลือก Default Formatting : Settings → ช่อง Default Formatter เลือกเป็น Prettier - Code formatter
ไฟล์ JSON Settings
{
"files.autoSave": "onFocusChange",
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.formatOnSave": true
}
2. Basic React
React คือ JavaScript Library ที่ใช้สำหรับ ทำ User Interfaces (UI) เป็นโอเพ่นซอร์สและถูกพัฒนาขึ้นจากทีม Facebook

แนวคิดของ React คือ
- แบ่งเว็บออกเป็นส่วนย่อยๆ เราเรียกมันว่า Component
- Component ช่วยให้เราไม่ต้องเขียนโค๊ดซ้ำๆ
- ในช่วงแรกๆ เริ่มมาจากแนวคิด Single Page Application (SPA)
- JSX ที่มีความคล้ายกับ HTML แต่มันคือ JavaScript ที่มีความสามารถเพิ่มขึ้น
การสร้าง Component
function MyButton() {
return <button>This is my button component</button>
}
- Component คือ UI ที่มี logic ภายใน หรือเป็นแค่ markup อย่างเดียวก็ได้
- เป็น function ธรรมดา ที่ return JSX
- เราจะสร้าง Component โดยแบ่งเป็นส่วนเล็กๆ แค่ Button หรือ Link หรือจะสร้าง Component 1 อัน ให้ render ทั้งหน้า ก็ได้ (อยู่ที่เราออกแบบ)
- แม้จะเป็น javascript function แต่ naming convention แนะนำให้ตั้งชื่อเป็น capital letter คือ ขึ้นต้นด้วยตัวพิมพ์ใหญ่ เช่น
MyButton
,Button
,Image
(จะได้ไม่ซ้ำกับ tag html ที่มีอยู่แล้ว) - เวลาที่เราจะ Return element ใน Component เราจะใช้
()
กรณีมีหลายบรรทัด
การเรียกใช้งาน Component เหมือนกับ การใช้งาน tag html ปกติเลย
<MyComponent></MyComponent>
เพียงแค่ใน React เมื่อเราไม่มี content ใน element เราสามารถใช้ closing tag ได้เลยแบบนี้
<MyComponent />
3. JSX และ Component
- JSX เป็น Markup Syntax หน้าตามัน คล้ายๆกับ HTML
- เราสามารถแทรกโค๊ด JavaScript ไปได้ หรือสั่ง execute javascript ใน JSX ได้
- ใน markup เวลาเราใช้
class
เราจะใช้className
แทน - ต้องมี close tag เสมอ
- Single Root Element ห้าม return multiple element (ต้อง wrap ให้เป็น 1 element)
ตัวอย่าง JSX ที่ผิด คือ ไม่สามารถ return multiple element แบบนี้ได้ และตัวอย่างที่ถูก คือ wrap เป็น 1 element
// ❌ return multiple element ไม่ได้
function MyComponent() {
return (
<h1>Hello World!</h1>
<p>This is component!</p>
)
}
// ✅ wrap มันด้วย div ซะ
function MyComponent() {
return (
<div>
<h1>Hello World!</h1>
<p>This is component!</p>
</div>
)
}
ในบางครั้ง เราไม่ต้องการ wrap มันด้วย div
เพิ่ม เพราะมันจะทำให้ เวลาเรา render HTML เรามีโค๊ด div
เพิ่มมา ทำให้ stylesheet ของเราผิดเพี้ยน เราสามารถ wrap element ด้วย การใช้ React.Fragment
หรือ ตัวย่อคือ <>
และ </>
แบบนี้
function MyComponent() {
return (
<React.Fragment>
<h1>Hello World!</h1>
<p>This is component!</p>
</React.Fragment>
)
}
// หรือใช้ short hand
function MyComponent() {
return (
<>
<h1>Hello World!</h1>
<p>This is component!</p>
</>
)
}
การแสดงค่า JavaScript หรือการแทรกโค๊ด JavaScript ลงไปใน JSX เราจะใช้ {}
ตัวอย่าง
function MyComponent() {
const title = 'Hello World!'
const message = 'This is component!'
return (
<div>
<h1>{title}</h1>
<p>{message}</p>
</div>
)
}
4. CSS
เราสามารถเพิ่ม Style ใน React ได้หลากหลายวิธีครับ
className
วิธีแรกคือใช้แบบ HTML/CSS ปกติได้เลย เพียงแต่ใช้ attribute ชื่อ className
แทนที่ class
แบบนี้
<img className="avatar" />
ที่มีไฟล์ css ดังนี้
/* In your CSS */
.avatar {
border-radius: 50%;
}
Inline-Style
เป็นการแทรก style แบบ inline คล้ายๆ HTML เพียงแต่ style แบบนี้ ต้องเป็น object เท่านั้น ตัวอย่าง
const myStyle = {
avatar: {
borderRadius: '50%'
}
}
<img style={myStyle.avatar} />
ข้อสังเกต ใน Style Object เราจะใช้ชื่อแบบ camelCase
นะครับ เช่น borderRadius
หรือ ตัวอย่างอื่นๆ คือ
font-size
→fontSize
text-algin
→textAlign
font-family
→fontFamily
และพวก properties value ถ้าไม่ใช่ number ก็จะเป็น string เช่นพวก สี, px ต่างๆ
CSS Modules
คล้ายๆกับ การใช้งาน CSS ปกติ เพียงแต่ว่า วิธีนี้ ข้อดีคือ แต่ละ Component จะถูก generate ชื่อแตกต่างกัน ทำให้ไม่ต้องกังวลว่า css เราจะไปชื่อซ้ำกับไฟล์อื่นๆ
วิธีการก็คือ ตั้งชื่อไฟล์ ลงท้ายด้วย .module.css
เช่น [name].module.css
ชื่อ style.module.css
.avatar {
border-radius: 50%;
}
และในไฟล์ JSX ก็ import และเรียกใช้งานแบบนี้
// 1 import css มาไว้ที่ตัวแปร styles
import styles from './style.module.css'
function MyComponent() {
return <img className={styles.avatar} />
}
เราจะสังเกตความแตกต่างจาก css ปกติ เมื่อเราเปิดเว็บ แล้วดู HTML Element จะเห็นว่าชื่อคลาส มันถูก generate จาก .avatar
เป็นรูปแบบ hash
อื่นๆ (Third Party / Library)
- SCSS/SASS - รองรับ SCSS/SASS ด้วย ซึ่งเราต้องติดตั้ง pre-processor เอง ส่วนนี้ผมไม่ได้ยกตัวอย่างนะครับ แค่พูดถึงว่า เราสามารถใช้ SCSS/SASS ได้เช่นกัน
- JS in CSS / CSS in JS - ส่วนนี้ไม่ใช่ React แต่เป็นพวก Third Party ต่างๆ เช่น Styled Component, Emotion


ส่วน CSS Library/ Framework ที่นิยมในโลกของ React.js (นอกจาก Bootstrap) คือ




5. Rendering List
กรณีที่เราต้องการ render Component ที่คล้ายๆ กันเช่น Profile
หรือ list ของ สิ่งของต่างๆ เราสามารถใช้ JavaScript Array map ได้ ตัวอย่าง ที่เห็นบ่อยๆ เช่น เราจะแสดง <ul>
และข้างในมี <li>
มีข้อมูลดังนี้
<ul>
<li>John Doe</li>
<li>Chuck Norris</li>
<li>Jane Doe</li>
<li>Foo Bar</li>
<li>Alice Bob</li>
</ul>
สิ่งที่ต้องทำคือ
- เปลี่ยนข้อมูล ให้อยู่ในรูปแบบ JavaScript Array
const names = [
'John Doe',
'Chuck Norris',
'Jane Doe',
'Foo Bar',
'Alice Bob'
]
2. ใช้ map เพื่อแปลงให้เป็น array ของ JSX nodes ชื่อ users
const users = names.map(name => <li>{name}</li>)
3. จากนั้น ใน component เราก็สามารถ ใช้แบบนี้ได้
function MyComponent() {
return <ul>{users}</ul>
}
นอกจากนี้ เราสามารถแทรก Map
ใน JSX ตรงๆ ภายใน return function ได้เลย โดยไม่ต้องสร้างตัวแปรก็ได้ แบบนี้
function MyComponent() {
return (
<ul>
{
users.map(user => {
return <li>{user}</li>
})
}
</ul>
)
}
ใน loop อย่าลืม return ด้วยนะครับ ตัวอย่าง
// ✅ arrow function แบบ return JSX (implicit return)
users.map(user => <li>{user}</li>)
// ❌ arrow function แต่ไม่ได้ return ค่า
users.map(user => {
<li>{user}<li>
})
// ✅ return JSX
users.map(user => {
return <li>{user}<li>
})
เราจะได้ Warning ว่า Each child in a list should have a unique "key" prop. ใน list items เราควรจะใส่ key ให้กับมันด้วย ตัวอย่าง จากปกติ ข้อมูล array string เราก็ทำเป็น data object โดยการใช้ id
const names = [
{ id: 1, name: 'John Doe' },
{ id: 2, name: 'Chuck Norris' },
{ id: 3, name: 'Jane Doe' },
{ id: 4, name: 'Foo Bar' },
{ id: 5, name: 'Alice Bob }
]
function MyComponent() {
return (
<ul>
{
users.map(user => {
return <li key={user.id}>{user.name}</li>
})
}
</ul>
)
}
หรือถ้าไม่มี id จริงๆ ก็ใช้ index ของ array ก็ได้ แต่ก็ไม่แนะนำเท่าไหร่ (กรณีที่ไม่มี id หรือ unique อื่นๆ จริงๆ เท่านั้น)
users.map((user, index) => <li key={index}>{user}</li>)

6. Condition Rendering
ใน JSX เราสามารถกำหนด condition ว่าจะ render Component ไหนหลายวิธี วิธีแรกคือ
If Else
ตัวอย่างการใช้ If Else ในการ render Component ถ้า score มากกว่า 50 ก็จะ render แบบนึง ถ้า น้อยกว่า 50 ก็จะอีกแบบ วิธีนี้จะใช้แบบ JavaScript คือการกำหนดเงื่อนไข และก็ assign JSX ไปเก็บไว้ที่ตัวแปรซักตัว
funciton MyComponent() {
let result
const score = 50
if (score >= 50) {
result = <p>You've passed!</p>
} else {
result = <p>Please try again next time</p>
}
return (
<div>
<p>Your result:</p>
{result}
</div>
)
}
ใช้ ? operator
คล้ายๆ If Else แต่วิธีนี้ คือเราใช้ภายใน JSX จากตัวอย่าง If Else ถ้าเราใช้ ? operator จะเป็นแบบนี้
funciton MyComponent() {
const score = 50
return (
<div>
<p>Your result:</p>
{score >= 50 ? (
<p>You've passed!</p>
) : (
<p>Please try again next time</p>
)}
</div>
)
}
อธิบายเพิ่มเติม คิดว่าน่าจะงงแน่นอน ตัว syntax ของ ? operator หรือ ternary operator คือ
condition ? exprIfTrue : exprIfFalse
ถ้าเงื่อนไข True ก็ execute อันแรก ถ้า False ก็จะ execute อันที่สอง (หลัง colon) พอมาดูดีๆ ตัว JSX เรา เปรียบเทียบเป็น
score >= 50 ? // condition
<p>You've passed!</p> // exprIfTrue
<pPlease try again next time</p> //exprIfFalse
logical &&
ในบางครั้ง เราต้องการแค่ condition เป็น If ไม่ต้องการ Else เราสามารถใช้ &&
ได้ ตัวอย่าง syntax คือ
condition && exprIfTrue
ผมจะให้ Component แสดงข้อความ You've passed ถ้า score มากกว่า 50 และไม่ต้องแสดงอะไรเลย ถ้าคะแนนน้อยกว่า 50 ก็จะได้แบบนี้
funciton MyComponent() {
const score = 50
return (
<div>
<p>Your result:</p>
{score >= 50 && (
<p>You've passed!</p>
)}
</div>
)
}
หรือตัวอย่างอื่นๆ อย่างเช่น ถ้าสมมติ เราทำระบบ Login ก็เช็คเงื่อนไข ถ้า logged in ก็ให้แสดงหน้า Dashboard ถ้าไม่ได้ Login ก็ให้แสดงหน้า Login แบบนี้
const isLoggedIn = true // สมมติ ได้ค่ามาจาก api
<div>
{isLoggedIn && <Dashboard />
</div>
7. Events
ต่อมาเรื่องของ Event ใน React เบื้องต้น เราจะพูดถึง onClick
ก็คือ รับ event เวลาที่ user ทำการ click ปุ่ม นั่นเอง
โดยปกติ ถ้าเป็น HTML & JS เราจะรับ events ผ่าน onclick
หรือใช้ addEventListener()
<button onclick="doSomething()">Click me</button>
<button id="click-me">Click me!</button>
<script>
const button = document.getElementById('#click-me')
button.addEventListener('click', () => {
// do something
})
</script>
ใน React เราก็จะใช้คล้ายๆ กันเพียงแต่ว่า onclick
จะเป็น onClick
(camelCase) และรับเป็น handler function แทนที่จะเป็น string
export default function MyButton() {
function handleClick() {
alert('You clicked me!')
}
return (
<button onClick={handleClick}>
Click me
</button>
)
}
จะเห็นว่าเราส่งแค่ functionhandleClick
เราจะไม่ execute มันนะครับ แบบนี้คือผิดonClick={handleClick()}
นอกจากนี้ events เราสามารถใช้ anonymous function ไปเลยก็ได้ ถ้าเกิดว่า function นั้นไม่ได้ต้องการอะไรซับซ้อน
<button onClick={() => alert('You clicked me!')}>
Click me
</button>
นอกจากนี้ ตัว handler function เรายังสามารถรับค่า ที่เราต้องการได้ เช่น สมมติ เรา loop list of items และต้องการกด click เพื่อแสดง id ของ item นั้นๆ ตัว handler function เราก็รับ id มาแบบนี้
export default function MyButton() {
function handleClick(id: number) {
alert(`You clicked ${id}`)
}
return (
<>
{
items.map(item => (
<button onClick={() => handleClick(item.id) }>
Click me
</button>
))
}
</>
)
}
8. Props
React Component จะใช้ props
ในการ รับ-ส่ง ข้อมูล ระหว่าง Component ตัว Parent Component สามารถที่จะส่งข้อมูล ไปหา Child Component ได้ ผ่าน props
(เหมือน HTML attributes) แต่ต่างกันตรงที่ เราสามารถ ส่งค่า JavaScript หรือ object array หรือ function ก็ได้
ตัวอย่าง ผมลองเปลี่ยน <li>
ใน MyComponent แยกไปเป็น Component ใหม่ ชื่อ Item
function Item() {
return <li>John Doe</li>
}
ทีนี้ เวลาเราใช้ Item
ก็จะเป็นแบบนี้
const names = [
{ id: 1, name: 'John Doe' },
{ id: 2, name: 'Chuck Norris' },
{ id: 3, name: 'Jane Doe' },
{ id: 4, name: 'Foo Bar' },
{ id: 5, name: 'Alice Bob }
]
function Item() {
return <li>John Doe</li>
}
function MyComponent() {
return (
<ul>
{
users.map(user => {
return <Item />
})
}
</ul>
)
}
ทีนี้จะสังเกตเห็นว่า ทุกๆ Item
มันยังแสดงแค่ John Doe ยังไม่ได้เป็นค่าจริงๆ ที่เราอยากให้เป็น วิธีการก็คือ สร้าง props ขึ้นมาใหม่ ผมตั้งชื่อว่า name ละกัน และส่งไปแบบนี้
<Item name={user.name} />
การรับค่า Props โดยปกติทุกๆ Component ตัว function จะรับ props
เป็น parameter อยู่แล้ว สามารถรับค่าผ่าน props ได้ แบบนี้
- ทำการกำหนด Props Types ให้มันก่อน เช่น
name
เป็นstring
interface Props {
name: string
}
2. กำหนด Type เป็น Props
ที่เราสร้างไว้
function Item(props: Props) {
return <li>{props.name}</li>
}
ซึ่งถ้า ตัว Parent เราส่ง props ชื่ออะไร ตัว Child Component เราก็สามารถ access ชื่อนั้นๆ ผ่าน props
ได้ เช่น ถ้าเรามีส่ง name, id, age อะไรก็แล้วแต่
function Item(props) {
const name = props.name
const id = props.id
const age = props.age
// const { name, id, age } = props
return <li>{name}</li>
}
ส่วนใหญ่แล้ว ส่วนใหญ่จะเขียนเป็น destructoring object มากกว่า แบบนี้
function Item({ name }) {
return <li>{name}</li>
}
เราสามารถ set default value ให้กับ props ได้ กรณีที่ถ้า Parent Component ไม่ได้ส่ง props มา เราก็ใช้ default value แบบนี้
function Item({ name, age = 0 }) {
return <li key={name}, {age} yrs.</li>
}
Code หลังจากใช้ default value
const names = [
{ id: 1, name: 'John Doe', age: 25 },
{ id: 2, name: 'Chuck Norris', age: 30 },
{ id: 3, name: 'Jane Doe', age: 23 },
{ id: 4, name: 'Foo Bar', age: 35 },
{ id: 5, name: 'Alice Bob }
]
function Item({ name, age = 0 }) {
return <li key={name}, {age} yrs.</li>
}
function MyComponent() {
return (
<ul>
{
users.map(({ id, name }) => {
return <Item key={id} name={name} />
})
}
</ul>
)
}
9. State
React State คือข้อมูลที่เราจะใช้ภายใน Component ต่างจาก Props ที่ใช้ส่งข้อมูลข้ามกันระหว่าง Component เราอ่าน Props จากภายนอก Component แต่ State อยู่ภายใน Component
- ทุกครั้งที่ State มีการเปลี่ยนแปลงค่า ตัว Component จะทำการ re-render
- การสร้าง state ใน React ตัว
useState
จะรับค่า initial value และ return ค่า Array กลับมา
import { useState } from 'react'
const states = useState(0)
// states จะได้เป็น array
// array[0] = state
// array[1] = function ที่ setState
เรามักจะเขียนแบบนี้ (Destructoring array)
import { useState } from 'react'
const [count, setCount] = useState(0)
- เราสามารถตั้งชื่อ state เป็นอะไรก็ได้
- ตัว function ที่ setState เช่นกัน สามารถตั้งชื่ออะไรก็ได้ แต่ naming convention นิยมตั้ง
setName
เช่น ถ้าcount
ก็setCount
ถ้า state ชื่อname
ก็setName
เป็นต้น
การ setState
ส่วนใหญ่ การ setState
จะทำก็ต่อเมื่อมี event หรือ condition อะไรซักอย่าง เช่น user click ปุ่ม Button หรือการ initial render ครั้งแรก (useEffect()
บทเรียนถัดไป)
ทุกๆ ครั้งที่ state มีการเปลี่ยนแปลงค่า ตัว Component จะทำการ re-render ใหม่ ฉะนั้น ระวังเรื่องการ update state จน infinity loop ด้วย
ตัวอย่าง เมื่อเมาท์คลิ๊ก จะทำการ set state และเปลี่ยนค่า Counter ซึ่ง ก็เหมือนกับโคีด default ที่เราขึ้นโปรเจ็ค Vite นั่นเอง (ค่า count
จะเพิ่มขึ้นทีละ 1 จากการกด)
import { useState } from 'react'
function App() {
const [count, setCount] = useState(0)
return (
<button onClick={() => setCount((count) => count + 1)}>
count is {count}
</button>
)
}
Object State
หากเราต้องการเก็บ state เป็น Object สิ่งแรกที่เราต้องทำคือ กำหนด Type ให้กับ Object ก่อน ว่าจะเป็นอย่างไร เช่น สมมติ เราจะเก็บ user
เรารู้ว่า user object ต้องมี id
กับ name
เราก็กำหนด Type ก่อน แบบนี้
interface User {
id: number
name: string
}
จากนั้น เวลาเรา initial state เราจะทำแบบนี้ (ใช้ Generic type)
const defaultUser = { id: -1, name: 'Default' }
const [user, setUser] = useState<User>(defaultUser)
หรือไม่มี default User ก็ให้เป็น undefined ก็จะเป็นแบบนี้ (ใช้ TypeScript Union (|
) หมายถึง User
หรือ undefined
const [user, setUser] = useState<User | undefined>()
การอัพเดท Object State
หากต้องการอัพเดท Object State เราจะใช้วิธีการสร้าง new object ขึ้นมา เพื่อ set state
const handleOnClick = () => {
const newUser = {
id: 2,
name: 'New name'
}
setUser(newUser)
}
กรณี ต้องการอัพเดท เพียงแค่ name
เราสามารถใช้ Spread Operator ได้
const handleOnClick = () => {
const newUser = {
...user,
name: 'New name'
}
setUser(newUser)
}
หรือใช้ Object destructoring ตอน setUser
เลยแบบนี้
setUser({ ...user, name: 'New name' })
10. Props & State and Events
State กับ Props ต่างกันอย่างไร?
- State เป็นค่าที่ใช้ภายใน Component อย่างเดียว
- เมื่อ state มีการเปลี่ยนแปลง ตัว component จะ re-render
- ตัว Props เป็นค่าที่เอาไว้ส่งข้อมูลระหว่าง component
- Props เปลี่ยน ตัว component ก็ re-render
- Props สามารถส่งค่าได้ทั้งตัวแปร หรือ function ก็ได้
- Component แม่ มีค่า props/state เปลี่ยน ตัว children component ก็จะ re-render เช่นกัน
Children Props
ปกติ เวลาเราจะส่งข้อมูลไปให้ components เราก็จะกำหนด เป็น props ใช่มั้ย แต่มี props ตัวนึงที่ไม่ต้องกำหนด เพราะมันเป็น children props ก็คือ สามารถเข้าถึงได้ผ่าน props.children
ตัวอย่าง
<MyComponent>
<h1>This is children header</h1>
<p>This is paragraph</p>
</MyComponent>
ข้อมูลข้างใน <MyComponent>
ทั้งหมด ก็คือ children ทีนี้ตัว MyComponent
เวลาเราสร้าง ก็จะมีหน้าตาแบบนี้
export default function MyComponent({ children } ) {
return (
<>
{children}
</>
)
}
Sharing state กับ components
ปกติเวลาที่เรา share state ระหว่าง component ทำได้แค่ จาก parent -> ไป children ใช่มั้ยครับ เราไม่สามารถที่จะส่งจาก children ไปหา parent ได้
กรณีที่เรามี component ซ้อนกันหลายๆชั้น และส่ง state ไปเป็นทอดๆ คงลำบากน่าดู มีวิธีนึงที่แนะนำก็คือ เรื่องของ lift up state ก็คือพยายาม นำ state ไปไว้ที่ตัว parent component แล้วค่อยส่งข้อมูล props ไป

การส่ง handle events function ผ่าน Props
ใช้ handle event function ผ่าน props เพื่อเปลี่ยน state ของ parent วิธีนี้คือ เราสามารถ ส่ง handler function ผ่าน props ไปให้ children ได้ และเมื่อมี event เกิดขึ้นตัว parent component ก็รับ event และทำการเปลี่ยนแปลงค่า state ตัวอย่างเช่น
import { useState } from 'react';
function MyButton({ handleClick }) {
return (
<button onClick={handleClick}>
Click me!
</button>
);
}
export default function Counter() {
const [count, setCount] = useState(0);
function handleClick() {
setCount(count + 1);
}
return (
<>
You pressed me {count} times
<MyButton handleClick={handleClick} />
</>
);
}
จบแล้วสำหรับตอนที่ 1 สำหรับตอนนี้ ก็จะเป็นพื้นฐานของ React เบื้องต้นนะครับ ลองฝึกฝน และทบทวนกันดู หากมีคำถาม สามารถสอบถามเข้ามาได้ตลอด ทั้ง Facebook Page หรือ Social media อื่นๆ ตามช่องทางที่ให้ไว้ในเว็บนะครับ
Workshop
ฝึกทำ Workshop & Mini Project ด้วย React.js

Happy Coding ❤️