หลังจากมีประสบการณ์จริง จากการลงมือทำโปรเจ็กต์นี้ เราคงพอจะเห็นภาพแล้วว่า Components, State, และ Props คืออะไร
เป้าหมาย
ในบทความนี้ เราจะสรุปความหมายของคำศัพท์ทั้ง 3 คำโดยละเอียดอีกครั้ง

Components
พื้นฐานสำคัญอย่างแรกที่เราต้องรู้ในการใช้ React คือ การมองโปรแกรม หรือ application ที่เราจะสร้างเป็นส่วนต่าง ๆ ประกอบรวมกัน แต่ละส่วนเราเรียกว่า “component”

เมื่อเราตั้งชื่อให้กับ component ต่าง ๆ แต่ละ component ก็จะมีชื่อดังนี้

เมื่อนำ components ต่าง ๆ มาสร้างเป็นไฟล์ .js เราก็จะได้ไฟล์ทั้งหมดดังภาพ

เวลาใช้งาน component เราจะเขียนมันเป็น Tag คล้าย ๆ Tag ของ HTML
index.js

App.js

ในการสร้าง component เราสร้างได้ 2 วิธี คือแบบ class และแบบ function การตัดสินใจในเบื้องต้นว่าจะสร้าง component เป็นแบบใด เราคิดง่าย ๆ แค่ว่า

Component ใดที่มีความซับซ้อน เช่น มีการเก็บ state หรือมีการใช้งาน lifecycle ที่ extends จาก Component ของ React เราจะสร้าง component นั้นเป็นแบบ class
App.js

แต่ถ้า component ทำหน้าที่แค่ render, ส่งค่า, หรือ คืนค่า jsx เราก็สร้างมันแบบ function แทน
VideoList.js

ในโปรเจ็กต์นี้ เรามี component แบบคลาส 2 components และแบบ function อีก 3 components

เมื่อกลับไปอ่านโค้ดดู จะพบว่า ทั้งคลาส App และ SearchBar ต่างก็มีการเก็บ state และที่ App มีการใช้งาน componentDidMount ซึ่งเป็น lifecycle ของ React ด้วย
App.js

SearchBar.js

State
โปรแกรมต่าง ๆ เกิดขึ้นมาเพื่อประมวลผลข้อมูล (data) บางอย่าง จากนั้นก็ส่งผลลัพธ์กลับมาให้ผู้ใช้งาน โปรแกรมที่เราสร้างขึ้นมาก็เช่นกัน

เรารับ data ที่ผู้ใช้กรอกเข้ามาทาง SearchBar เมื่อกดที่ปุ่ม Enter ข้อมูลโปรแกรมก็จะนำค่าที่ได้รับมาไปใช้งาน
นั้นคือ การส่ง data ไปให้ API ของ Youtube นำไปค้นหาวีดีโอที่ตรงกับคำนั้น และส่งรายการวีดีโอผลลัพธ์ที่ได้กลับมาให้เราแสดงผลที่หน้าจอ
กลับมาโฟกัสกันที่คำว่า “state” state คือข้อมูลที่เราเก็บเอาไว้ใน component เราเก็บมันไว้ในรูปแบบ object คือมีคีย์หรือชื่อที่เราตั้งให้ และค่าของข้อมูลที่ต้องการเก็บเอาไว้
ในไฟล์ SearchBar.js เราเราเก็บ state เป็นคำค้นที่ผู้ใช้งานกรอกเข้ามา โดยมีชื่อว่า term มีค่าเริ่มต้นเป็น string ว่าง ๆ

และที่ไฟล์ App.js เราเก็บ state ที่เป็น videos และ selectedVideo เอาไว้

โดย videos ใช้เก็บรายการวีดีโอที่ได้รับมาจาก Youtube API อยู่ในรูปแบบ array
และ selectedVideo เป็นรายการวีดีโอที่ถูกเลือกมาแสดงผลที่ส่วนของ VideoDetail เรากำหนดค่าเริ่มต้นให้เป็น null
ค่าข้อมูลใน state เป็นค่าที่เปลี่ยนแปลงอยู่ตลอดเวลา ตามการใช้งานของผู้ใช้
เมื่อผู้ใช้กรอกคำค้นหาใหม่ ค่า state ใน SearchBar (term) ก็เปลี่ยนแปลงไป
เมื่อกดปุ่ม Enter ค่า state ใน App (videos) ก็เปลี่ยนไปตามผลลัพธ์ข้อคำค้นหาใหม่
เมื่อผู้ใช้คลิกที่รายการวีดีโอใด ๆ ค่า state ใน App (selectedVideo) ก็เปลี่ยนไปตามที่ถูกคลิก
การเปลี่ยนแปลงของ state ทำให้การแสดงผลของ component เปลี่ยนแปลงไปด้วย
เช่น แสดงผลวีดีโอตามคำค้นใหม่ หรือ แสดงรายการวีดีโอที่ส่วน VideoDetail ใหม่ตามที่ผู้ใช้คลิกเลือกมา
พอจะมองเห็นการทำงานของ state หรือยังคะ มันคล้าย ๆ กับคำว่า “สถานะ” หรือ “status” ที่ขับเคลื่อนการทำงานของระบบ ทำให้ component รู้ว่าจะต้องทำงานอะไรหรือแสดงผลอย่างไร

Props
Props ย่อมาจากคำว่า properties หน้าที่ของมันแตกต่างอย่างสิ้นเชิงกับ state เพราะเราใช้ props เพื่อสื่อสารระหว่าง component
ยังจำได้มั้ยคะ เวลาสร้าง component เราสร้างมันแบบนี้
Component แบบ class

Component แบบ function

แต่เวลาใช้งาน เราใช้มันในรูปแบบ Tag แบบนี้

แล้วที่บอกว่า props คือการสื่อสานกันระหว่าง component มันสื่อสารกันอย่างไร?
เราจะหาคำตอบนี้ด้วยการดูความสัมพันธ์ของแต่ละ component กันค่ะ
App -> SearchBar
ใน App เรามี method หรือ function ชื่อ onTermSubmit ทำหน้าที่
– รับคำค้น (keyword) ที่ user ใช้ในการค้นหาวีดีโอมา
– ส่งคำนั้นไปให้ API ของ Youtube ทำงาน
– ได้ผลลัพธ์กลับมา set ค่าให้ state

ในส่วนของเมธอด render เราใช้งาน <SearchBar /> ด้วยการกำหนด tag และส่ง “props” ชื่อ onFormSubmit ไปให้ไฟล์ SearchBar.js ทำงาน

แล้ว onFormsubmit ทำงานอย่างไร?
การที่การเรากำหนดว่า onFormSubmit={this.onTermSubmit} หมายความว่าเมื่อ props ชื่อ onFormSubmit ถูกเรียกใช้งาน หมายถึง การเรียกใช้งานเมธอด onTermSubmit นั้นเอง

แล้วที่ SearchBar.js รับค่า props มาใช้งานยังไง?
การใช้งานหรือเข้าถึง props ใน class ทำได้ง่าย ๆ ด้วยคำสั่ง this.props.onFormSubmit ดังนี้

จะเห็นว่า ตอนเรียกใช้ this.props.onFormSubmit เราส่งค่า this.state.term ไปให้เมธอด (onTermSubmit) ใช้งานด้วย

พอจะเห็นการคุยกันระหว่าง App และ SearchBar หรือยังคะ ? ถ้ามันคุยกันได้จริง App ก็คงจะพูดประมาณว่า
App: เอ้ย SearchBar ฉันส่ง props onFormSubmit ไปให้นายนะ ตอนเรียกใช้งานมัน ช่วยส่งส่งค่า keyword ที่นายรับมาจาก user ให้ฉันด้วยล่ะ
SearchBar: ได้เลยลูกพี่!

App -> VideoList
ในไฟล์ App เรามี state ที่ใช้เก็บ videos คือวีดีโอผลลัพธ์ 5 รายการ และ selectedVideo คือวีดีโอที่ถูกเลือกให้แสดงผลที่ส่วนของ VideoDetail
videos ได้ค่ามาจากการที่ user กรอก keyword และกดปุ่ม Enter โปรแกรมก็จะนำ keyword ส่งให้ Youbube API นำค่าไปค้นหาวีดีโอ
และส่งรายการวีดีโอที่เป็นผลลัพธ์กลับมาให้เราจำนวน 5 รายการ ซึ่งเก็บอยู่ในรูปแบบ array
selectedVideos ได้ค่ามาจากการเรียกใช้งานเมธอด onVideoSelect การทำงานงานของมันคือ ทำการรับค่าวีดีโอที่ถูกคลิกเลือกเข้ามา และนำไป set ให้กับ state ในส่วนของ render() เราส่ง state เป็น porps ให้กับ <VideoList /> จำนวน 2 properties คือ onVideoSelect และ videos

videos คือผลลัพธ์รายการวีดีโอ 5 รายการที่เก็บอยู่ใน state เราส่งมันไปให้ VideoList.js นำค่านี้ไป render ข้อมูลวีดีโอแต่ละรายการออกมา
onVideoSelect ก็คือเมธอด onVideoSelect ใน App.js นั่นเอง เราส่งเมธอดนี้ไปใน <VideoList /> แต่ <VideoList /> ไม่ได้ใช้ มันเป็นแค่ทางผ่าน เพื่อส่ง props ต่อไปให้ <VideoItem /> เท่านั้น

ถ้า 2 conponents นี้คุยกัน คงจะคุยประมาณว่า
App: เอ้ย! VideoList.js ฉันส่ง props vidoes ไปให้นายนะ เอาไปใช้ในการแสดงผลรายการวีดีโอแต่ละรายการได้เลย และฝากเมธอด onVideoSelect ไปให้ VideoItem.js ด้วย
VideoList: Okay!

VideoList -> VideoItem
ใน VideoList เราใช้งาน <VideoItem /> โดยการสร้าง tag ข้อมูลรายการวีดีโอแต่ละรายการขึ้นมา ตามจำนวน videos ที่มีทั้งหมด ผ่านทางเมธอด map()

จากนั้นก็ส่งต่อ prop ไปให้ <VideoItem /> จำนวน props 3 properties คือ key, video, และ onVideoSelect

key: คือค่า videoId แต่ละรายการที่ดึงออกมา เราใช้มันเพื่อระบุความแตกต่างของแต่ละ <VideoItem />
video: คือค่าวีดีโอ ที่เราดึงมาจากรายการวีดีโอใน array จะเห็นว่า คำนี้ video ไม่เติม –s คือรายการวีดีโอรายการเดียว ต่างจากคำว่า videos ที่หมายถึงรายการวีดีโอหลายรายการที่เก็บอยู่ใน array
onVideoSelect: คือเมธอดที่ App.js ฝากมาให้ <VideoList /> ส่งต่อไปให้ <VideoItem /> เรียกใช้งาน
มาที่ VideoItem.js เรารับค่า props มาจาก <VideoList /> จำนวน 2 properties คือ video และ onVideoSelect

เราเรียกใช้ onVideoSelect ใน <div> ของข้อมูล เป็นแบบ onClick พร้อมกับส่งค่า video ไปให้เมธอดนำค่าไปใช้งานด้วย (กรณีเป็น function ไม่ต้องใช้ this)

จะสังเกตเห็นว่า components ระดับบนคุยกับ component ระดับล่าง เราส่งมันมาผ่าน props มาตามลำดับ แต่ตอน component ระดับล่างคุยกับ component ระดับบน เราสามารถคุยผ่านการเรียกใช้งาน method ได้เลย

สุดท้าย video จาก porps ที่ส่งมา เราก็นำค่าไปแสดงผลที่หน้าจอ

ครั้งนี้เรามี components คุยกันถึง 3 component แต่ก็ยังไม่ถือว่าซับซ้อนมากนัก เพราะ component สุดท้าย ทำหน้าที่แค่
– รับ props มา
– เรียกใช้เมธอด
– render ข้อมูลเท่านั้น
App -> VideoDetail
ใน App.js ใช้งาน <VideoDetail /> และส่ง props ชื่อ video ไปให้

Video คือ ค่าใน selectedVideo ใน state เป็นค่าวีดีโอที่ถูกคลิกเลือกให้มาแสดงนั้นเอง
ใน VideoDetail.js เรารับค่า video มา มีการตรวจสอบว่า ถ้าไม่มีค่า (null) ก็จะแสดงคำว่า Loading… แทน

การทำงานของ component นี้ก็ไม่มีอะไรซับซ้อน แต่นำค่า video มาแสดงผลเท่านั้น

สรุป
Components คือส่วนประกอบต่าง ๆ ของโปรเจ็กต์
State คือค่าข้อมูลที่เก็บอยู่ใน components
Props ย่อมาจาก Properties เราใช้มันในการสื่อสารระหว่าง components
ก้าวต่อไป
หลังจากปูพื้นฐานด้วยการทำความเข้าใจคำศัพท์ 3 คำนี้แล้ว ก้าวต่อไปเราจะไปเรียนรู้เรื่องของ Redux ที่จะมาช่วยให้เราจัดการกับ state ได้ง่ายขึ้น
และเรื่อง Hooks ที่จะทำให้เราสร้าง component ในรูปแบบ function แต่สามารถใช้ state หรือใช้ lifecycle ได้
แล้วพบกันใหม่ในบทความต่อไปนะคะ 🙂 Bye!
Sources
