React Fundamentals
Introduction to React.js
React คืออะไร ?
React เป็น Library สำหรับการสร้าง User Interface ของภาษา JavaScript
ย้อนกลับไปสมัยก่อน
- สมัยก่อน Website เวลาเราจะกดไปหน้าใหม่ เช่น จากหน้า Home ไปหน้า Shopping, Website จะไปโหลดหน้า Shopping มาจาก Server
- แต่ JavaScript จะมาช่วยเรา เช่น เวลาเรากดไปหน้าใหม่ มันจะโหลดข้อมูลมาไว้รอแล้ว ดังนั้นผู้ใช้จะรู้สึกใช้งาน Website ได้เร็วขึ้น
JavaScript จะรันใน Browser ในหน้าเว็บที่ถูกโหลดมา โดยเราสามารถปรับแต่ง HTML ของหน้าเว็บได้จาก JavaScript ดังนั้นเราไม่จำเป็นต้องรอ Server ส่งข้อมูลหน้าเว็บมาใหม่
แล้ว React มาช่วยอะไร ?
- เป็น Client-side JavaScript Library
- เป็น Library สำหรับเขียนเว็บสมัยใหม่ ที่สามารถทำให้ UI โต้ตอบกับผู้ใช้งานได้
- ในเว็บทั่วไปแล้ว ที่ไม่ได้ซับซ้อนอะไรมาก การใช้ JavaScript อย่างเดียว เป็นสิ่งที่โอเคและใช้งานสะดวก แต่เมื่อเว็บนั้น ซับซ้อนมากขึ้น การแก้ไข DOM ก็จะทำได้ยากและซับซ้อนมากขึ้น
- เว็บที่สร้างด้วย React จะเป็น Single-Page-Application (SPAs)
อะไรคือ Single-Page_Application
- React จะสามารถควบคุมส่วนต่าง ๆ ของ HTML ในหน้าเว็บได้ทั้งหมด
- เว็บที่เป็น multi-page-application จะมีบางหน้าที่ต้อง Render และโหลดมา จาก Backend
- ส่วน Single-Page-Application ตัว Backend (server) จะส่งหน้าเว็บ HTML มาครั้งแรกครั้งเดียว หลังจากนั้นเมื่อเรากดไปหน้าไหน React ก็จะจัดการ ทั้งหมด โดยไม่ต้องไปโหลดมาจาก Backend อีกรอบ
ข้อดีของ React
- มี Virtual DOM - Virtual DOM เป็นตัวเทียบว่าต้องไปแก้ไข DOM ตัวไหนใหม่บ้าง ถ้าไม่มีตัวที่แตกต่าง มันก็จะไม่เข้าไปแก้ไข แต่ถ้ามีความแตกต่างระหว่าง DOM และ Virtual DOM จากนั้น React จะทำการเข้าไปแก้ไข DOM เฉพาะแค่ตัวที่มีการเปลี่ยนแปลง
- ข้อมูลจะส่งจากบนลงล่าง - การส่งข้อมูลจะเป็นแบบ one-way data flow, ข้อมูลจะถูกส่งจากตัวแม่ไปตัวลูกเท่านั้น (ลงด้านล่างเท่านั้น)
- Components base - React สามารถทำ Components ได้ ยกตัวอย่างเช่น เราสร้าง Header Component ขึ้นมา เพื่อใช้กับหน้า Home เราก็สามารถใช้ Header กับหน้าอื่น ๆ ได้เช่นกัน
- Learn once, Write Everywhere - React สามารถประยุกต์เขียนได้หลาย Platform เช่น เราเขียน Website จาก React, เราก็สามารถเขียน React Native ที่เป็นการสร้าง Mobile Application ทั้ง Android และ IOS และเราก็สามารถเขียน Electron ที่เป็น Desktop App ที่รันได้บนทุก OS
การ Setup สําหรับการเขียน React
วิธีสร้าง React App มีหลายวิธี แต่ในคอร์สนี้เราจะใช้ vite ช่วยเราในการสร้าง React App
โดยเราจะพิมพ์คำสั่ง npm create vite ใน Command line และ Setup ตามที่เราต้องการ
Element
พวกปุ่มหรือสิ่งต่าง ๆ ที่เราเห็นกันบนหน้าเว็บที่สร้างด้วย React เกิดจาก
React.createElement ,ReactDOM.render() ซึ่ง Function นี้จะทําให้เกิด React Element เกิดขึ้น
React.createElement()จะทําให้เกิด ReactElement ขึ้น- Element หน้าตาเหมือนกับ tag ใน HTML
- Element เป็นข้อมูลประเภท Obj
ReactDOM.render()จะนํา Element ที่เป็น Obj มาแสดงผลที่ DOMReactDOM.render()จะทําการจับคู่ Element กับ tag ใน DOM ที่จะทําการแสดงผล
หน้าตาของ Element
const element = <h1>Hello, world</h1>;
หน้าตาของ root DOM ใน HTML
<div id="root"></div>
ทุกอย่างใน tag นี้จะถูกจัดการด้วย React DOM
ReactDOM.render
ReactDOM.render(element, document.getElementById('root’));
จะจับคู่ Element และ root DOM ใน HTML
Element คืออะไร ?
Element ****ก็คือสิ่งที่ใช้ในการกําหนดว่าหน้า Website ว่าจะมีหน้าตา เป็นอย่างไรคล้าย ๆ กับการใช้ HTML Tag
React.createElement(type, props, children)
- type - ชื่อของ tag
- props - เหมือน attribute ของ tag และ เป็นข้อมูลประเภท Obj
- children - ข้อมูลภายใน tag
ข้อกําหนดของ type
- ถ้าชื่อ type เหมือน tag HTML ให้ใช้ตัวอักษรอังกฤษตัวพิมพ์เล็กทั้งหมด
- ถ้าชื่อ type ไม่มีใน tag HTML ให้ขึ้นต้นด้วยตัวอักษรอังกฤษตัวพิมพ์ใหญ่
ข้อกําหนดของ props
- Props เป็นข้อมูลประเภท Object
- key ของ Object เปรียบเสมือน attribute ของ tag
ข้อกําหนดของ children
- สามารถเป็น number, string และ React.createElement() ได้
- ข้อมูลที่อยู่ใน children จะถูกแสดงผลออกมาบนหน้า Website
EX1
React
React.createElement('h1', {style:{color: 'blue'}}, “Hello, world!”)
เหมือนกับการเขียน HTML แบบนี้
<h1 style="color:blue">Hello, world!</h1>
ผลลัพธ์

EX2
React
React.createElement("div", null,
React.createElement("h1", null, "Hello React!"),
React.createElement("p", null, "This is paragraph"),
React.createElement("button", null, "click me")
);
เหมือนกับการเขียน HTML แบบนี้
<div>
<h1>Hello React!</h1>
<p>This is paragraph</p>
<button>click me</button>
</div>
ผลลัพธ์

EX3
React
React.createElement("div", null,
React.createElement("h1", null, "Hello React!"),
React.createElement("p", null, "This is paragraph"),
React.createElement("button", null, "click me"),
React.createElement("ul", null,
React.createElement("li", null, "Coffee"),
React.createElement("li", null, "Tea",
React.createElement("ul", null,
React.createElement("li", null, "Black tea"),
React.createElement("li", null, "Green tea",
React.createElement("ul", null,
React.createElement("li", null, "China"),
React.createElement("li", null, "Africa")
)
)
)
),
React.createElement("li", null, "Milk")
)
);
เหมือนกับการเขียน HTML แบบนี้
<div>
<h1>Hello React!</h1>
<p>This is paragraph</p>
<button>click me</button>
<ul>
<li>Coffee</li>
<li>Tea
<ul>
<li>Black tea</li>
<li>Green tea
<ul>
<li>China</li>
<li>Africa</li>
</ul>
</li>
</ul>
</li>
<li>Milk</li>
</ul>
</div>
ผลลัพธ์

JSX คืออะไร
JSX คืออะไร
จากปัญหา
React.createElement("div", null,
React.createElement("h1", null, "Hello React!"),
React.createElement("p", null, "This is paragraph"),
React.createElement("button", null, "click me"),
React.createElement("ul", null,
React.createElement("li", null, "Coffee"),
React.createElement("li", null, "Tea",
React.createElement("ul", null,
React.createElement("li", null, "Black tea"),
React.createElement("li", null, "Green tea",
React.createElement("ul", null,
React.createElement("li", null, "China"),
React.createElement("li", null, "Africa")
)
)
)
),
React.createElement("li", null, "Milk")
)
);
JSX จะมาช่วยแก้ปัญหานี้
JSX คืออะไร
- JSX ย่อมาจาก JavaScript Syntax Extension
- จะใช้สําหรับสร้าง UI ของ React แทน React.createElement
- JSX คือ syntax ที่รวม JavaScript กับ XML เข้าด้วยกัน ที่หน้าตาคล้าย HTML โดยปกติแล้วต้องใช้ควบคู่กับ Transpiler เช่น Babel ซึ่งจะทําให้ เราเขียนได้ง่ายขึ้น
- JSX สามารถเขียน JavaScript expression ภายในส่วนต่าง ๆ ของ element ได้
ข้อกำหนด
- JSX ต้องเป็นแท็กปิดเสมอ เช่น ใน HTML จะเขียนแบบนี้ได้
<br>แต่ใน JSX จะต้องเป็น<br/> - ถ้าเป็นแท็กเปิดต้องมีแท็กปิดเสมอ เช่น
<Content> JSX </Content> - การ return JSX จะ return แค่ Element เดียวเท่านั้น
- สามารถใช้ tag แบบไม่มีชื่อ
<> </>ได้ด้วย แต่เมื่อ render จะไม่เห็น tag นี้ - การใช้ JSX ต้องอยู่ใน scope ของ react (ต้องมี
import “React” from “react”สําหรับเวอร์ชั่นเก่า)
ข้อกําหนด
-
จะใช้ className แทน class ในการกําหนดชื่อคลาส
HTML
<div class="App">
เนื้อหาที่แสดงใน App Component
</div>JSX
<div className="App">
เนื้อหาที่แสดงใน App Component
</div> -
Tag
labelจะใช้htmlForแทนforHTML
<label for="name">
Name
</label>JSX
<label htmlFor="name">
Name
</label> -
Attribute จะใช้ camelCase ทั้งหมด
HTML
<label onclick="name">
Name
</label>JSX
<label onClick="name">
Name
</label>
การเพิ่ม CSS ใน JSX (Styling ใน React)
การ Styling หรือการตกแต่ง JSX จะมีหลัก ๆ ดังนี้
- Inline
- Plain CSS
- CSS Module
- etc.
ที่จริงมีแบบอื่นอีกแต่เราจะเรียนกันแค่ 2 แบบก่อน ซึ่งถ้าอยากศึกษาเพิ่มเติม สามารถกดลิ้งก์ด้านล่างได้เลย https://www.freecodecamp.org/news/how-to-style-react-apps-with-css
การใส่ CSS แบบ Inline
- เขียน CSS properties ใน object และใส่ไปให้กับ props (Attribute) ที่ชื่อว่า “style”
- CSS properties ที่เขียนใน JSX จะต้องเป็น camelCase เช่น
background-colorจะต้องเขียนเป็นbackgroundColor
Inline
ตัวอย่างการเขียนแบบ Inline - แบบที่ 1
class MyHeader extends React.Component {
render() {
const mystyle = {
backgroundColor: "red"
};
return (
<div>
<h1 style={mystyle}>Hello Style!</h1>
<p>Add a little style!</p>
</div>
);
}
}
ตัวอย่างการเขียนแบบ Inline - แบบที่ 2
หรือเราสามารถเพิ่ม CSS properties เข้าไปใน JSX เลยก็ได้
class MyHeader extends React.Component {
render() {
return (
<div>
<h1 style={{
backgroundColor: "red"
}}
>Hello Style!</h1>
<p>Add a little style!</p>
</div>
);
}
}
Plain CSS
CSS
.box-wrapper {
text-align: center;
max-width: 950px;
margin: 0 auto;
border: 1px solid #e6e6e6;
padding: 40px 25px;
margin-top: 50px;
}
JSX
import "./styles.css";
class MyHeader extends React.Component {
render() {
return (
<div className="box-wrapper">
<h1>Hello Style!</h1>
<p>Add a little style!</p>
</div>
);
}
}
ขั้นตอนการใช้งาน Plain CSS
- ต้อง import ไฟล์ styles.css ในไฟล์ Component
- หลังจากนั้นก็ใส่ชื่อ className ให้ตรงกับ CSS เช่น
box-wrapperของ Element ให้ตรงกับ CSS
Expression
- การแสดงผล JavaScript expression ใน element จะใช้ ครอบ
- คําสั่งที่ใช้ได้มีดังนี้
- print variable (แสดงค่าตัวแปร)
- conditional (ternary) operator (If แบบย่อ)
- การคํานวณ
- เรียกใช้ function
- อื่น ๆ
สมมติเรามีค่าบางอย่างที่เป็นตัวแปร ต้องการที่จะใส่เข้าไปใน JSX เราก็สามารถใช้ ครอบ แล้วใส่ตัวแปรลงไปได้ เช่น
<div className="App" value={...}>
{...}
</div>
JavaScript expression มีอะไรบ้าง
- ข้อมูลประเภทต่าง ๆ เช่น string, number, boolean, null, undefined
- โครงสร้างข้อมูล (Data structure) เช่น array , object
- ตัวดําเนินการ (Operator) เช่น && , || , !, + , - , * , /
- Logic Operator (ตัวดำเนินการทางตรรกะ) เช่น if, else if , else และ ternary
- function
ตัวอย่างการใช้ JavaScript Expression
ตัวแปรข้อมูลประเภทธรรมดา
const msg = 'hello world!'
const arr = ['arr1', 'arr2', 'arr3']
<div>
<div>{msg}</div>
<div>{arr}</div>
</div>
Logic Operator (Ternary)
const a = true
<div>{a ? 'this is true' : 'this is false'}</div>
การนํา Array มาใช้ร่วมกับ map function ทําให้เป็น Element
let boo = false
let arr = ["a","b","c"]
<div className="App" value={boo ? "have" : "no have"}>
{arr.map(item => <p> {item}</p>)}
{arr}
</div>
การใช้ && Operation
const showMsg = true
const msg = 'hello world!'
<div>{showMsg && msg}</div>
การคํานวณทางคณิตศาสตร์
<div>result of 2 + 2: {2 + 2}</div>
<div>result of 2 - 2: {2 - 2}</div>
<div>result of 2 ÷ 2: {2 / 2}</div>
<div>result of 2 x 2: {2 * 2}</div>
การใช้ฟังก์ชัน
const title = 'cLiCk me';
<button>{title.toUpperCase()}</button>
แต่ JavaScript Expression ก็มีข้อจำกัดด้วย
- เราไม่สามารถแสดงผลข้อมูล
boolean,null,undefinedบนหน้าเว็บได้ - โครงสร้างข้อมูล (เช่น Array, Object) แสดงผลบนหน้าเว็บได้เฉพาะ Array
ตัวอย่างเช่น
<div/>
<div></div>
<div>{false}</div>
<div>{null}</div>
<div>{undefined}</div>
<div>{true}</div>
ค่า false, null, undefined และ true จะไม่ถูกแสดงออกมาให้เห็นในเว็บ
Component
คอมโพเนนต์ (Components) คืออะไร
- ใน React จะประกอบด้วย Component โดยจะถูกแบ่งออกเป็น Component ย่อย ๆ
- แนวคิดการแบ่ง UI ของเว็บออกมาเป็นส่วนๆ ภายใน Component มี logic ของตัวเอง ทําให้สามารถนํามาใช้ใหม่ (Reuse) ได้ทั้งเว็บ
- และการแบ่ง Component จะช่วยแบ่ง Logic ต่าง ๆ ออกเป็นย่อย ๆ เพื่อช่วยไม่ให้เกิด การรวมกันของ Logic ขนาดใหญ่ไว้ในที่เดียว (ไว้ใน function เดียว)
- โดย Components ใน React จะมี 2 ประเภท
- Function Component
- Class Component
โดยเราสามารถสร้าง Component ได้ 2 แบบ หลัก ๆ
เขียนแบบ Function declaration
import React from "react";
function Person(props) {
return (
<div>
<h1>Hello, {props.name}</h1>
</div>
)
}
export default Person;
เขียนแบบ Arrow function
import React from "react";
const Person = props => {
return (
<div>
<h1>Hello, {props.name}</h1>
</div>
)
}
export default Person;
มีอีกรูปแบบนึงที่สามารถทำได้เหมือนกัน แต่เราจะยังไม่เน้นในคอร์สนี้
import React from "react";
class Person extends React.Component {
render() {
return (
<div>
<h1>Hello, {this.props.name}</h1>
</div>
)
}
}
export default Person;

ข้อดีของ Component
- การนํากลับมาใช้ซํ้า (Reuse)
- Component แต่ละอันที่สร้างมา ตอนหน้า Home page เราสามารถนําไปใช้ซํ้าได้ตอนที่สร้างหน้า หน้าใหม่ เช่น EmployeePage
- การไม่รวมโค้ดไว้ที่เดียว
- การที่เราแยกเป็น Component ย่อย ๆ แต่ละ Component ก็จะทํางานแค่อย่างเดียว เช่น EmployeeListItem ทําหน้าที่ แสดง ชื่อ ตําแหน่งและภาพ ส่วน EmployeeList ก็ทําหน้าที่ แสดง EmployeeListItem ส่วน SearchBar ก็ทําหน้าที่ Search แต่ถ้าเราไม่แบ่งเป็น Component ย่อย ๆ โค้ดทั้งหมด ที่พูดมาอยู่ใน Component เดียว ก็จะทําให้โค้ดอ่านยากและซับซ้อน
Component VS Element
ก่อนอื่น เราจะใช้โค้ดนี้ในการอ้างอิง
import React from "react";
function Person(props) {
return (
<div>
<h1>Hello, {props.name}</h1>
</div>
)
}
export default Person;
โดยก้อนที่เราจะเรียกเป็น Component ก็จะมีดังนี้
function Person(props) {
return (
<div>
<h1>Hello, {props.name}</h1>
</div>
)
}
และก้อนที่เป็น Element หรือก็คือ JSX Tag
<div>
<h1>Hello, {props.name}</h1>
</div>
โดย element ตัวแรกคือ <div> และตัวที่สองคือ <h1>
และตอนสุดท้าย โค้ด JSX จะถูกแปลงเป็น React.createElement()
import React from "react";
class Person extends React.Component {
render() {
return
React.createElement("div", null,
React.createElement("h1", null, "Hello, ", props.name)
);
}
}
export default Person;
ส่งข้อมูลผ่าน Props
สมมติว่าเรามีตัวแปร name ที่เก็บค่า “Potion” ไว้อยู่ let name = "Potion" และเรามี Custom Component
ที่สร้างขึ้นมาชื่อ Item โดยเราต้องการให้ Item แสดงผล name ออกมา ซึ่งแน่นอนว่าปัญหาคือตัวแปร name อยู่ใน App Component ไม่ได้อยู่ใน Item Component

ซึ่งตัว Item Component ก็ไม่สามารถเข้าถึงตัวแปร name นี้ได้
แต่เราสามารถใช้ Props เพื่อส่งข้อมูล (เช่น ตัวแปร name) จาก App Component ไปยัง Item Component ได้ โดยเพิ่ม Attribute ชื่อ Text และเข้าถึงข้อมูลนั้นผ่าน Attributes ใน Item Component

HTML Elements มี Attributes เช่น style <div style="background:black">test</div> React Custom Components ก็สามารถกำหนด Attributes ได้เช่นกัน แนวคิดการส่งข้อมูลให้ Component ลูก จะเรียกว่า Props ไม่ใช่ Attributes
ตัวอย่างการใช้งาน
เวลาเราส่งพวก props name surname และ age ไป มันก็จะกลายเป็น key และ value
ใน object props เพราะฉะนั้นเวลาเรียนใช้ เราจึงต้อง props.name ,props.surname
ภายใน Component
function StudentItem(props) {
return (
<div className="StudentItem">
<div>{props.name}</div>
<div>{props.surname}</div>
<div>{props.age}</div>
</div>
)
การใช้งาน Component
<StudentItem name="Tom" surname="Cruise" age={25} />
หน้าตาของ Props Object
{
name: "Tom",
surname: "Cruise",
age: 25
}
EVENT
ที่ผ่านมา เราได้เขียนเว็บที่มีแค่ข้อมูล และไม่สามารถโต้ตอบกับผู้ใช้งานได้หรือเรียกว่า Static Website ในบทนี้ เราจะมาทำให้ Website ของเราสามารถโต้ตอบกับผู้ใช้งานได้ โดยการใช้ State และ Event ซึ่งเราจะมาพูดถึง Event กันก่อนว่า Event ใน React คืออะไร
Event คืออะไร ?
Event คือ Action การกระทําที่เกิดขึ้น โดยโปรแกรมสามารถตรวจจับได้
ตัวอย่างเช่น
- User กดปุ่ม
- User กดคีย์บอร์ด
การกระทําเหล่านี้คือ Event
Event สำคัญอย่างไร ?
โดย Event นั้นจะทำให้เราสามารถรู้ได้ว่า User นั้น ต้องการจะทำอะไร เช่น User ต้องการจะ Save ก็กดปุ่ม Save, หลังจาก User กดปุ่ม Save ต่อไป Event ก็จะส่งไปให้เว็บไซต์รู้ หลังจากนั้น Website ก็จะทำการ Save ตามที่ User ต้องการ
ตัวอย่างการใช้งาน Event
HTML
<button onclick="changeStatus()" > Click me </button>
React
<button onClick={changeStatus()}>Click me</button>
ข้อแตกต่างของ HTML และ React คือ onClick ของ React นั้นจะเป็น camelCase และจะครอบด้วย {...}
เราสามารถใส่ได้หลายแบบ โดยการใส่เค้าไปใน JSX เลย เรียกว่า Inline function
การใช้ Arrow function
<button onClick={() => {console.log("Clicked")}}>Click me</button>
การใช้ Function keyword
<button onClick={function(){console.log("Clicked")}}>Click me</button>
แต่ปกติแล้วเราจะประกาศ Function ไว้ข้างบนก่อน และค่อยนำมาใช้ด้านล่าง
const clickEventHandler = () => {
console.log("Clicked")
}
return (
<div className="App">
<button onClick={clickEventHandler}>Click me</button>
</div>
);
คําเตือน คนผิดกันบ่อย เราไม่ต้องใส่ () ตอนที่เราใส่เข้าไปใน onClick
const clickEventHandler = () => {
console.log("Clicked")
}
return (
<div className="App">
<button onClick={clickEventHandler()}>Click me</button>
</div>
);
เพราะว่า เราต้องการจะส่ง Function clickEventHandler ให้ React และ React จะไปรันตอนถูก Click เท่านั้น ดังนั้น เราไม่จำเป็นต้องใส่ () หลัง Function
State
State คืออะไร
State ใน React คือ สิ่งที่เอาไว้เก็บข้อมูลที่จะถูกใช้ใน React Component มันจะคล้ายๆกับ ตัวแปรตัวหนึ่ง แต่เมื่อมีการเปลี่ยนแปลง React จะมีการ Re-render เพื่อ update ข้อมูลในหน้า เว็บ (ใน DOM)
วิธีการใช้ State
-
การที่เราจะใช้ State เราต้องสร้าง State ผ่าน Funtion
useState -
ขั้นตอนแรก เราต้อง Import
useStateเข้ามาก่อนimport { useState } from "react";import React, { useState } from "react";
function Example() {
// Declare a new state variable, which we'll call "count"
const [count, setCount] = useState(0);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>Click me</button>
</div>
);
} -
การเรียกใช้งานจะมีรูปแบบดังนี้
const [state, setState] = useState(initialValue);โดยที่stateคือ ค่าที่เราจะเอาไว้ใช้งานsetStateคือ Function สําหรับการใช้เปลี่ยนค่าของ StateinitialValueคือ ค่าเริ่มตอนของ State นั้น
const [count, setCount] = useState(0); -
การอธิบายแบบละเอียด
ที่จริง
useStateจะ return ออกมาเป็น array โดยตัวแรกเป็น state ตัวที่สองเป็น function ที่ใช้สําหรับ เปลี่ยนค่าของ state นั้น ซึ่งปกติจะนิยมเขียนโดยการใช้ Destructuring ออกมาเป็นสองตัวเลยแบบนี้const [state, setState] = useState(initialValue);โดยที่ตัวแรกstateจะเป็นค่าของ state ส่วนsetStateจะเป็นฟังก์ชันที่ใช้ในการเปลี่ยนค่า (ทั้งสองฝั่งมีค่าเท่ากัน)
ข้อควรระวังของ useState - useState เป็นหนึ่งใน Hook function ของ React ซึ่งต้องใส่ Component เท่านั้น และไม่อยู่ในฟังก์ชันใด ๆ ของ Components
การเขียนที่ถูกต้อง
import React, { useState } from "react";
function Example() {
// Declare a new state variable, which we'll call "count"
const [count, setCount] = useState(0);
const countHandler = () => {
setCount(count + 1);
};
return (
<div>
<p>You clicked {count} times</p>
<button onClick={countHandler}>Click me</button>
</div>
);
}
const [count, setCount] = useState(0); ต้องอยู่ภายใน Function
การเขียนที่ไม่ถูกต้อง
import React, { useState } from "react";
const [count, setCount] = useState(0); //แบบนี้ไม่ได้ เพราะไม่ได้อยู่ภายใน Function
function Example() {
const countHandler = () => {
setCount(count + 1);
};
return (
<div>
<p>You clicked {count} times</p>
<button onClick={countHandler}>Click me</button>
</div>
);
}
การเขียนที่ไม่ถูกต้อง
import React, { useState } from "react";
function Example() {
const countHandler = () => {
const [count, setCount] = useState(0); //แบบนี้ก็ไม่ได้เพราะอยู่ใน function ของ Components
setCount(count + 1);
};
return (
<div>
<p>You clicked {count} times</p>
<button onClick={countHandler}>Click me</button>
</div>
);
}
useState เป็นหนึ่งใน Hook function ของ React ซึ่งต้องใส่ Function Component เท่านั้น และ
ไม่อยู่ในฟังก์ชันใด ๆ ของ Components
การนำ State ไปใช้งาน - เราสามารถนำ State ไปใช้ได้เลย เหมือนกับตัวแปรตัวหนึ่ง โดยต้องครอบด้วย {...}
import React, { useState } from "react";
function Example() {
// Declare a new state variable, which we'll call "count"
const [count, setCount] = useState(0);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>Click me</button>
</div>
);
}
การเปลี่ยนค่าของ State - การเปลี่ยนค่า State โดยใช้ setState การเปลี่ยนค่าของ state เราจะเรียกฟังก์ชัน setState และใส่ค่าที่ต้องการลงไป
import React, { useState } from "react";
function Example() {
// Declare a new state variable, which we'll call "count"
const [count, setCount] = useState(0);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>Click me</button>
</div>
);
}
setState()
- ใช้เปลี่ยนค่า state ใน component
- การทํางานคือการนําค่าตัวใหม่ไปแทนที่ state ตัวเก่า เช่น setState (ค่าใหม่)
- หลังจาก state มีการเปลี่ยนแปลง setState ตัว React จะ re-render หน้าเว็บใหม่
- setState() ทํางานแบบ async (ค่าจะยังไม่เปลี่ยนแปลงทันที)
ใส่เป็น Arrow Function ให้กับ onClick โดยใน Arrow Function จะมีฟังก์ชัน setCount อยู่
import React, { useState } from "react";
function Example() {
// Declare a new state variable, which we'll call "count"
const [count, setCount] = useState(0);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>Click me</button>
</div>
);
}
เมื่อมีการ Click จะทําให้สิ่งที่อยู่ข้างใน Arrow Function นั่นก็คือ setCount ทํางาน
การ setState นี้คือนําค่า state เก่านั่นก็คือค่า count เก่ามาบวกเพิ่มไป 1
HOOKS
useEffect
การที่เราจะใช้ useEffect เราต้องมาเข้าใจก่อนว่า "Effect" หรือ "Side Effect" คืออะไร
โดยปกติแล้ว React จะทําหน้าที่ในการ Render หน้าเว็บและจัดการ State ต่าง ๆ ซึ่งการกระทําอะไรก็ตามที่ไม่อยู่ในขอบเขตของ React จะเรียกว่า Side Effect หรือเรียกว่า Effect ก็ได้ เช่น
- การส่ง Request ไปขอข้อมูลจาก Server
- การใช้ API ของ Browser เช่น การเรียกออฟเจ็กต์ document และ window โดยตรง
- การใช้ฟังก์ชัน setTimeout หรือ setInterval
แล้วทําไมต้องแยกการกระทําบางอย่างออกมาเป็น side effect ให้มันยุ่งยาก?
เพราะว่าการกระทําที่เป็น side effect จะไม่สามารถคาดการณ์ผลลัพธ์ได้ (unpredictable) เช่น การส่ง Request ไปขอข้อมูลจาก Server อาจจะสําเร็จ รอนาน (ในกรณีที่ Server ช้า) หรือล้ม เหลว (ในกรณีที่ Server ล่ม)
ซึ่ง side effect ถ้ามารวมกับ code ของ react อาจจะทําให้เกิด bug หรือไปขัดขวางการ Render
ของ React, React จึงมีฟังก์ชัน useEffect ให้เราใช้ เพื่อใช้สําหรับแยก code ที่เป็น Side Effect ออกมา
การใช้ useEffect
useEffect(() => {
// code here
}, [dependencies]);
useEffect จะมี 2 ส่วน คือส่วนของโค้ด ที่เราต้องการให้ทำงาน และ dependencies คือ โค้ดจะรันเมื่ออ dependencies มีการเปลี่ยนแปลง
โดยการรันของ useEffect จะถูกแบ่งเป็น 3 กรณี
-
การไม่ใส่ dependencies โค้ดจะถูกรันเมื่อ
- ครั้งแรกที่ Component render (หรือเรียกว่า Mount)
- ทุกครั้งหลังที่ re-render เสร็จ (Component evaluated)
useEffect(() => {
console.log('first render and every after rendering')
});
//ตัวนี้จะรันทุก ๆ รอบที่มีการ re-render -
ใส่เป็นอาเรย์ว่างโค้ดนี้จะถูกรันเมื่อ
- ครั้งแรกที่ Component render ครั้งเดียวเท่านั้น
useEffect(() => {
console.log('first render only once')
}, []);
//ตัวนี้จะไม่ถูกรันแล้วเพราะรันแค่รอบแรกรอบเดียว -
ใส่ denpendencies โค้ดนี้จะถูกรันเมื่อ
- ครั้งแรกที่ Component render
- จะถูกรันเมื่อ name หรือ age มีการเปลี่ยนแปลง
useEffect(() => {
console.log(`first render and when ${state} or ${props} are updated`)
}, [name, age])
//ตัวนี้จะถูกรันก็ต่อเมื่อ name หรือ age มีการเปลี่ยนแปลง
useEffect ทั้ง 3 ตัวอย่างแรกมาใส่พร้อมกัน ทันทีที่ Component mounted (render รอบแรก) ทั้ง 3 ตัวจะถูกรันทั้งหมด เพราะว่า useEffect จะรัน 1 ครั้งตอนที่ component mounted เสมอ
useReducer
useReducer ใช้สําหรับจัดการ state คล้ายๆ กับ useState
แต่ในบางครั้งถ้าเรามี state ที่ซับซ้อนมากขึ้น เช่น เรามี state หลาย ๆ อันที่สัมพันธ์กัน
(บางอันเปลี่ยนอีกอันเปลี่ยนตาม)
การใช้ useState จะเริ่มยาก และมีสิทธิที่เราจะเขียนผิดพลาดและเกิด bug ได้ง่าย
ในกรณีนี้เราสามารถใช้ useReducer แทน useState ได้ เพื่อการจัดการที่มีประสิทธิภาพ
มากขึ้น (สําหรับ state ที่ซับซ้อน)
const [state, dispatchFn] = useReducer(reducerFn, initialState, initFn)
- state - เป็นตัวแปรที่ใช้ใน Component
- dispatchFn - เป็นตัวที่ใช้ในการเปลี่ยนแปลง State
- reducerFn - เป็น Function ที่ใช้บอกว่า State จะเปลี่ยนยังไง
- initialState - ค่าเริ่มต้นของ State
- initFn - Function ที่ใช้กำหนดค่าของ initialState
Flow การทำงานของ Reducer

การใช้ useReducer
Action Object คืออะไร
- (Require) เป็น Object ที่ต้องมี properties ที่ชื่อ type
- property นี้ ต้องใช้ใน reducer
- (Optional) จะมี Properties อย่างอื่นด้วยก็ได้
- ขึ้นอยู่กับความจําเป็น แต่ไม่จําเป็นต้องมีก็ได้
- ตัวที่เหลือนี้จะถูกเรียกว่า payload
หน้าตาของ Action Object
const action = {
type: 'add',
user: {
name: 'John Smith',
email: 'jsmith@mail.com'
}
};
Reducer คืออะไร
Reducer เป็นตัวบอกว่า เราจะ update state อย่างไร
- เป็นฟังก์ชันที่ใช้ในการบอกว่าเราจะ update state ยังไง
- โดยมันจะรับ state ปัจจุบัน กับ action object มาจาก component ที่ dispatch มาให้
- object ที่ส่งออกไป React จะไป update ให้ใน State ของ useReducer
function reducer(state, action) {
if (action.type === "incremented_age") {
return {
age: state.age + 1,
};
} else if (action.type === "decremented_age") {
return {
age: state.age - 1,
};
}
}
ตัวอย่างการใช้งาน useReducer
function reducer(state, action) {
if (action.type === "incremented_age") {
return { age: state.age + 1 };
}
}
function App() {
const [state, dispatch] = useReducer(reducer, { age: 42 });
return (
<>
<button onClick={() => dispatch({ type: "incremented_age" })}>
Increment
</button>
<p>Hello! You are {state.age}</p>
</>
);
อย่างแรกเราจะมี Function reducer ที่ใช้กำหนดว่าเราจะเปลี่ยน State อย่างไร หลังจากนั้น ถ้าเรากดปุ่ม มันจะเรียกใช้ Function dispatch และใส่ Action Object เข้าไป และ Function reducer จะทำหน้าที่ตรวจสอบเงื่อนไข และ คืนค่า State อันใหม่กลับออกไป
ความแตกต่างระหว่าง useReducer และ useState
ปกติแล้ว useReducer จะใช้เมื่อเวลาเราใช้ useState แล้วรู้สึกยุ่งยากหรือใช้ useState แล้วมีบัคเกิดขึ้นเยอะ
useState
-
useStateนั้น ค่อนข้างที่จะใช้งานได้ง่ายกว่าและมักจะใช้
useStateก่อน -
useStateจะดีสําหรับ state/data ที่เป็นอิสระต่อกัน (Independent -
useStateจะดีเมื่อเราต้องการ เปลี่ยนแปลง state แบบตรงไปตรงมา
useReducer
- เมื่อเริ่มยุ่งยากแล้วใช้
useReducerเพื่อให้จัดการได้ง่ายขึ้น useReducerอาจจะถูกใช้เมื่อเรามี state/data ที่มีความสัมพันธ์กัน (dependent/related data)useReducerจะช่วยได้เมื่อเราต้องการเปลี่ยนแปลง state แบบที่ซับซ้อนมากขึ้น
context
สมมติว่าเรามีข้อมูลชุดหนึ่ง ต้องการจะส่งไปที่ Component ลูก ตัวอื่น ๆ เราไม่สามารถส่งไปตรง ๆ ได้ ดังนั้น เราจะต้องส่งข้าม Parent ไปเรื่อย ๆ จนถึง Component ลูกตัวนั้น

ตัวอย่าง

สมมติเรามีโค้ด ที่ Diagram หน้าตาประมาณนี้ ถ้าเราต้องการจะส่งข้อมูลจาก App ไปที่ img
เราจะต้องส่งข้อมูลผ่าน Props ลงไปเรื่อย ๆ จนถึง img ซึ่งจะทำให้โค้ดดูเยอะ และทำให้สับสนได้
โค้ดของ PlaceImage.jsx
function PlaceImage({ place, imageSize }) {
return (
<img
src={getImageUrl(place)}
alt={place.name}
width={imageSize}
height={imageSize}
/>
);
}
สังเกตได้ว่า Function จะรับ Props ลงมาเรื่อย ๆ จาก App
แต่ถ้าเรามี context เราก็จะสามารถส่งข้อมูลโดยที่ไม่ต้องส่งผ่าน Props ลงไปเรื่อย ๆ ได้
จาก image-context.js
import { createContext } from "react";
export const ImageContext = createContext(100);
เราก็สามารถลบ Props imageSize ออกได้
เมื่อใช้ useContext
function PlaceImage({ place }) {
const imageSize = useContext(ImageContext);
return (
<img
src={getImageUrl(place)}
alt={place.name}
width={imageSize}
height={imageSize}
/>
);
}
ImageContext.Provider
แล้วถ้าเราต้องการที่จะรับค่าตั้งแต่ Component แม่ไปถึง Component ลูกเลยล่ะ
เช่น เราต้องการจะใช้ค่า imageSize ตั้งแต่ ImageList ไปจนถึง img
เราสามารถใช้ Provider มาช่วยได้
const imageSize = isLarge ? 150 : 100;
return (
<>
<LoginPanel
currentUser={currentUser}
setCurrentUser={setCurrentUser} />
<label>
<input
type="checkbox"
checked={isLarge}
onChange={(e) => {
setIsLarge(e.target.checked);
}}
/>
Use large images
</label>
<hr />
<ImageContext.Provider value={imageSize}>
<ImageList />
</ImageContext.Provider>
</>
);
โดยเมื่อเรานำ ImageContext.Provider มาใช้ Component ภายน ImageList ก็จะสามารถใช้งาน imageSize ผ่าน useContext ได้เลย
PlaceImage.jsx
function PlaceImage({ place }) {
const imageSize = useContext(ImageContext);
return (
<img
src={getImageUrl(place)}
alt={place.name}
width={imageSize}
height={imageSize}
/>
);
}
สรุป
- useContext จะไปดึงค่าจาก Provider ที่ใกล้มันที่สุด
- ถ้าไม่มี Provider มันก็จะไปเอาค่า Default จาก Context มาใช้