การเปลี่ยนค่า Object ใน state ของ React.js
สวัสดีครับ จริงๆ บทความนี้ก็เป็นกึ่งๆ อ่านสรุป + แปลจากต้นฉบับแหละครับ ตัวอย่างโค๊ด และคำอธิบาย ก็อ่านจากเว็บ reactjs และผมก็ไม่ได้เอามาทั้งหมด ฉะนั้นใครต้องการความเข้าใจมากกว่านี้ แนะนำอ่านจากเว็บต้นฉบับดีกว่า เพราะเค้ามีตัวอย่างประกอบ เข้าใจง่ายขึ้น ถ้าได้เห็น ได้ลองแก้โค๊ดไปด้วย
State ใน React.js เราสามารถจะเก็บค่าอะไรก็ได้ โดยปกติทั่วๆไป ก็พวก number string bool รวมถึง Object หรือ Array ใช่มั้ยครับ ซึ่งวันนี้เราจะมาพูดถึงการเก็บ state แบบ Object กัน
ข้อสำคัญในการเก็บ state เป็น Object
- ควรมอง object ใน state ให้เป็น read-only
- ถ้าจะอัพเดท state ต้องสร้าง object ใหม่ หรือ copy เอา (จะไม่แก้ไข object เดิม)
- การแก้ไข object เดิม ตัว React.js จะไม่รู้ว่า state มีการเปลี่ยน และจะไม่ถูก re-render
โดยปกติ เราจะไม่ทำแบบนี้
แต่จะใช้วิธี Copy หรือสร้าง object ใหม่แทน แบบนี้
เรื่องของ Nested Object
บางครั้ง เราก็เก็บ state เป็น object หลายๆ ชั้น เหมือนกันใช่มั้ย (แต่จริงๆ ไม่ควรเท่าไหร่) แล้วเราจะอัพเดทมันยังไง? ตัวอย่างโค๊ด (จากเว็บ beta.reactjs.org)
สมมติ เราจะอัพเดทค่า พวก artwork.city
artwork.title
ถ้า Object ปกติเราก็ mutate เปลี่ยนค่ามันตรงๆได้เลย แบบนี้
แต่ React เราไม่สามารถไป mutate object ที่มัน render ไปแล้วได้ และ React มันก็ไม่รู้ว่า state มันเปลี่ยน วิธีการให้ React รู้ว่า state เปลี่ยน คือทำผ่าน useState ( setPerson ) เท่านั้น
ตัวอย่างการใช้ spread operator ( … ) ในการ Copy Object
ข้อควรระวังเรื่อง nest object บางครั้ง มันก็ไม่ใช่การ copy object จริงๆ เนื่องจาก object ใน JavaScript ใช้วิธี reference ตัวอย่าง
ถ้าเราเปลี่ยนค่า obj2.artwork.title
จะเห็นว่า obj3
และ obj1
ก็เปลี่ยนด้วย เพราะว่า obj3.artwork
มัน refenrece ไปหา obj1
นั่นเอง
จริงๆ เรื่องของ nest object state ถ้าเลี่ยงได้ ก็น่าจะเลี่ยง และจริงๆ ก็ไม่ควรเก็บหลายชั้นมากๆ หรือถ้าเลี่ยงไม่ได้จริงๆ ตาม structure ของที่ออกแบบไว้ ก็ต้องไปดูพวก concept flattening, normalized หรือใช้ library อย่าง immer.js ช่วย (อาจจะไม่ค่อยเหมาะกับมือใหม่)
สรุป
- ถ้าเรามี 2 state และมักจะอัพเดทพร้อมกัน แนะนำ merge เป็น อันเดียวดีกว่า
- การเลือก state และการวางโครงสร้าง state ควรคำนึงถึงความง่าย และลดข้อผิดพลาดด้วย เช่น ถ้าเรา nest object หลายๆชั้น หรือแยกกันเยอะเกินไป อะไรพวกนี้
- ไม่ควร เก็บค่า props ใส่ state นอกจากจะไม่ต้องการให้มัน update
- พวก UI เช่น select dropdown, options พวก state ที่เราเลือก ควรเก็บเป็น id ดีกว่า object
- ถ้า nest object มันอ่านยาก และซับซ้อน ให้ flattening มันซะ
Happy Coding ❤️
Reference
- Authors
-
Chai Phonbopit
เป็น Web Dev ในบริษัทแห่งหนึ่ง ทำงานมา 10 ปีกว่าๆ ด้วยภาษาและเทคโนโลยี เช่น JavaScript, Node.js, React, Vue และปัจจุบันกำลังสนใจในเรื่องของ Blockchain และ Crypto กำลังหัดเรียนภาษา Rust