useState และ useEffectใน react

Pimpineej
Tencent (Thailand)
Published in
3 min readAug 6, 2020

--

อย่างที่ทราบกันว่าการเขียน React Components นั้นมี 2 แบบคือ Class Component และ Function Component ( Stateless Component)
ซึ่งหากเราต้องการจะเขียน component โดยมีการเพิ่ม features หรือ action ต่างๆ จะต้องเขียนในรูปแบบของ Class Component ซึ่งเป็น component ที่มีการเก็บ state และสามารถเรียกใช้งาน lifecycle hooks ต่างๆ ได้

แต่โดยส่วนมากเราจะเริ่มเขียนจาก Function Component ก่อน และเมื่อมีการเพิ่ม features ทำให้เราต้องปรับการเขียนเป็นแบบ Class Component ซึ่งการทำแบบนี้ค่อนข้างยุ่งยากและเสี่ยงต่อความผิดพลาดได้ง่าย จึงมีการพัฒนา React Hooks เข้ามาช่วยให้เราสามารถเขียน function โดยไม่ต้อง implement Class นั่นเองค่ะ

*ก่อนที่เราจะใช้ React Hooks อยากให้ลองอ่าน React Lifecycle
(สามารถอ่านสรุปการเลือกใช้งานได้ที่บทความ
อธิบาย React Lifecycle แต่ละอันมีหน้าที่อย่างไร หรือ
สรุปการเลือกใช้งาน React 16.4+ component life-cycle methods )

แนะนำการใช้ State Hook หรือ useState

ตัวอย่างการเขียน code ด้านบนนี้จะเป็นการเขียน setState แบบ Class Component จะเห็นได้ว่าแค่การ set state พื้นฐานนั้น code ก็ใช้ code ที่ค่อนข้างยาว ซึ่งหากเราต้องการใช้ state เพิ่มอีกหลายตัว การอ่านและแก้ไข code ก็จะยิ่งยากขึ้นไปอีกค่ะ

จาก code ด้านบนเราจะเปลี่ยนมาใช้ useState ในการเขียนเพื่อ setState ซึ่งจะเขียนได้แบบนี้ค่ะ

การเขียน setState แบบ ใช้ useState Hook

พอเปลี่ยนมาใช้ useState ที่เขียนโดยการใช้ Function Component จะเห็นได้ว่า code สั้นลง ดูง่ายขึ้น หากต้องการจะเพิ่ม state ก็สามารถทำได้แค่เพิ่ม const [] = useState และเวลาเรียกใช้ก็ไม่ต้องเขียน this.state ต่อหน้าอีกด้วยค่ะ

ต่อกันที่ useEffect ซึ่งเราเอามาใช้เมื่อมีการเปลี่ยนแปลงเกิดขึ้นใน Component เป็น Hook ที่มีปัจจัยภายนอกเข้ามาเกี่ยวข้องกับตัว function component เช่น การแก้ไขพวก window, title หรือเรียก lifecycle ของ React เช่น componentDidMount
componentDidUpdate
เป็นต้น

เพื่อความเข้าใจมากยิ่งขึ้นเราลองมาใช้ useState กับ useEffect ดูค่ะ
โจทย์ที่เราจะทำคือ

เมื่อเปิดหน้ามาครั้งแรกจะให้แสดงคำว่า
Hi there, how are you?
หลังจากนั้น 1 วินาที ให้เปลี่ยนเป็นคำว่า
I'm fine, thanks for asking.

เริ่มต้นเราจะใช้ useState ตั้ง state เริ่มต้นเป็น string คำว่า
Hi there, how are you?

set state โดยใช้ useState
ผลลัพธ์หลังจาก run component

หลังจากนี้จะหน่วงเวลาไว้ 1 วินาที แล้วให้ message นี้เปลี่ยนเป็น
I'm fine, thanks for asking. ซึ่งการทำแบบนี้จะถือเป็น effect ที่เกิดขึ้นใน component ในส่วนของ Commit phase (ส่วนหลังจาก render component)

คำสั่งการหน่วงเวลาเราจะใช้ setTimeout ที่เป็น Method สำหรับการตั้งเวลาการทำงานตามที่กำหนดแล้วไม่ทำอีก โดยหากเขียนแบบ Class Component นั้นเราจะวาง setTimeout ไว้ที่ componentDidMount แต่ถ้าเราใช้ hook ก็คือวางในส่วนของ useEffect นั่นเอง

setTimeout ใน componentDidMount
setTimeout ใน useEffect

โดยใน setTimeout เราจะ setMessage เป็น I'm fine, thanks for asking.
เมื่อ run ผลลัพธ์ที่ได้จะแสดงดังนี้

ผลลัพธ์หลังจาก run component

แต่ว่าถ้าเราดูจาก console.log จะขึ้น trigger use effect hook 2 รอบ เนื่องจาก ในรอบแรกมันจะ run หลังจาก App render และรอบที่ 2 คือเกิดจากการ render lifecycle ค่ะ (useEffect จะ run ทุกครั้งที่มีการ render หรือทุกครั้งที่มีการ update นั่นเอง)

console.log ใน useEffect

ซึ่งในกรณีที่เราใช้ effect เยอะๆ นั้นอาจทำให้เกิด side-effects แปลกๆ หรือทำให้การทำงานหยุดชะงักได้เช่นกัน ทางแก้คือเราจะต้องทำให้ effect เกิดขึ้นครั้งเดียวตอน render ครั้งแรก โดยที่เราจะมี array ที่เป็น argument ส่งไปเป็นค่า [] เพื่อบอก React ว่า effect นี้ไม่ได้ขึ้นอยู่กับ props หรือ state ใดๆ เพื่อให้ไม่ต้อง re-run อีก

code ที่ปรับเพิ่ม []

ลองดูตัวอย่างการใช้ได้ที่ codesandbox ด้านล่างนี้เลยค่ะ

หวังว่าบทความนี้จะทำให้เข้าใจเรื่อง useState และ useEffect ไม่มากก็น้อยนะคะ หากมีอะไรแนะนำ feedback กลับมาก็ยินดีมากๆ เลยค่ะ

บทความอ้างอิง

--

--