React:Project Videos #22 สรุปโปรเจ็กต์

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

เป้าหมาย

ในบทความนี้ เราจะสรุปความหมายของคำศัพท์ทั้ง 3 คำโดยละเอียดอีกครั้ง

ภาพที่ 1

Components

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

ภาพที่ 2

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

ภาพที่ 3

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

ภาพที่ 4

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

index.js

ภาพที่ 5

App.js

ภาพที่ 6

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

ภาพที่ 7

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

App.js

ภาพที่ 8

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

VideoList.js

ภาพที่ 9

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

ภาพที่ 10

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

App.js

ภาพที่ 11

SearchBar.js

ภาพที่ 12

State

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

ภาพที่ 13

เรารับ data ที่ผู้ใช้กรอกเข้ามาทาง SearchBar เมื่อกดที่ปุ่ม Enter ข้อมูลโปรแกรมก็จะนำค่าที่ได้รับมาไปใช้งาน

นั้นคือ การส่ง data ไปให้ API ของ Youtube นำไปค้นหาวีดีโอที่ตรงกับคำนั้น และส่งรายการวีดีโอผลลัพธ์ที่ได้กลับมาให้เราแสดงผลที่หน้าจอ

กลับมาโฟกัสกันที่คำว่า “state” state คือข้อมูลที่เราเก็บเอาไว้ใน component เราเก็บมันไว้ในรูปแบบ object คือมีคีย์หรือชื่อที่เราตั้งให้ และค่าของข้อมูลที่ต้องการเก็บเอาไว้

ในไฟล์ SearchBar.js เราเราเก็บ state เป็นคำค้นที่ผู้ใช้งานกรอกเข้ามา โดยมีชื่อว่า term มีค่าเริ่มต้นเป็น string ว่าง ๆ

ภาพที่ 14

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

ภาพที่ 15

โดย videos ใช้เก็บรายการวีดีโอที่ได้รับมาจาก Youtube API อยู่ในรูปแบบ array

และ selectedVideo เป็นรายการวีดีโอที่ถูกเลือกมาแสดงผลที่ส่วนของ VideoDetail เรากำหนดค่าเริ่มต้นให้เป็น null

ค่าข้อมูลใน state เป็นค่าที่เปลี่ยนแปลงอยู่ตลอดเวลา ตามการใช้งานของผู้ใช้

เมื่อผู้ใช้กรอกคำค้นหาใหม่ ค่า state ใน SearchBar (term) ก็เปลี่ยนแปลงไป

เมื่อกดปุ่ม Enter ค่า state ใน App (videos) ก็เปลี่ยนไปตามผลลัพธ์ข้อคำค้นหาใหม่

เมื่อผู้ใช้คลิกที่รายการวีดีโอใด ๆ  ค่า state ใน App (selectedVideo) ก็เปลี่ยนไปตามที่ถูกคลิก

การเปลี่ยนแปลงของ state ทำให้การแสดงผลของ component เปลี่ยนแปลงไปด้วย

เช่น แสดงผลวีดีโอตามคำค้นใหม่ หรือ แสดงรายการวีดีโอที่ส่วน VideoDetail ใหม่ตามที่ผู้ใช้คลิกเลือกมา

พอจะมองเห็นการทำงานของ state หรือยังคะ มันคล้าย ๆ กับคำว่า “สถานะ” หรือ “status” ที่ขับเคลื่อนการทำงานของระบบ ทำให้ component รู้ว่าจะต้องทำงานอะไรหรือแสดงผลอย่างไร

ภาพที่ 16

Props

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

ยังจำได้มั้ยคะ เวลาสร้าง component เราสร้างมันแบบนี้

Component แบบ class

ภาพที่ 17

Component แบบ function

ภาพที่ 18

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

ภาพที่ 19

แล้วที่บอกว่า props คือการสื่อสานกันระหว่าง component มันสื่อสารกันอย่างไร?

เราจะหาคำตอบนี้ด้วยการดูความสัมพันธ์ของแต่ละ component กันค่ะ


App -> SearchBar

ใน App เรามี method หรือ function ชื่อ onTermSubmit ทำหน้าที่

– รับคำค้น (keyword) ที่ user ใช้ในการค้นหาวีดีโอมา
– ส่งคำนั้นไปให้ API ของ Youtube ทำงาน
– ได้ผลลัพธ์กลับมา set ค่าให้ state

ภาพที่ 20

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

ภาพที่ 22

แล้ว onFormsubmit ทำงานอย่างไร?

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

ภาพที่ 22

แล้วที่ SearchBar.js รับค่า props มาใช้งานยังไง?

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

ภาพที่ 23

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

ภาพที่ 24

พอจะเห็นการคุยกันระหว่าง App และ SearchBar หรือยังคะ ?  ถ้ามันคุยกันได้จริง App ก็คงจะพูดประมาณว่า

App: เอ้ย SearchBar ฉันส่ง props onFormSubmit ไปให้นายนะ ตอนเรียกใช้งานมัน ช่วยส่งส่งค่า keyword ที่นายรับมาจาก user ให้ฉันด้วยล่ะ

SearchBar: ได้เลยลูกพี่!

ภาพที่ 25

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

ภาพที่ 26

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

onVideoSelect ก็คือเมธอด onVideoSelect ใน App.js นั่นเอง เราส่งเมธอดนี้ไปใน <VideoList /> แต่ <VideoList /> ไม่ได้ใช้ มันเป็นแค่ทางผ่าน เพื่อส่ง props ต่อไปให้ <VideoItem /> เท่านั้น

ภาพที่ 27

ถ้า 2 conponents นี้คุยกัน คงจะคุยประมาณว่า

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

VideoList: Okay!

ภาพที่ 28

VideoList -> VideoItem

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

ภาพที่ 29

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

ภาพที่ 30

key: คือค่า videoId แต่ละรายการที่ดึงออกมา เราใช้มันเพื่อระบุความแตกต่างของแต่ละ <VideoItem />

video: คือค่าวีดีโอ ที่เราดึงมาจากรายการวีดีโอใน array จะเห็นว่า คำนี้ video ไม่เติม –s คือรายการวีดีโอรายการเดียว ต่างจากคำว่า videos ที่หมายถึงรายการวีดีโอหลายรายการที่เก็บอยู่ใน array

onVideoSelect: คือเมธอดที่ App.js ฝากมาให้ <VideoList /> ส่งต่อไปให้ <VideoItem /> เรียกใช้งาน

มาที่ VideoItem.js เรารับค่า props มาจาก <VideoList /> จำนวน 2 properties คือ video และ onVideoSelect

ภาพที่ 31

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

ภาพที่ 32

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

ภาพที่ 33

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

ภาพที่ 34

ครั้งนี้เรามี components คุยกันถึง 3 component แต่ก็ยังไม่ถือว่าซับซ้อนมากนัก เพราะ component สุดท้าย ทำหน้าที่แค่

– รับ props มา
– เรียกใช้เมธอด
– render ข้อมูลเท่านั้น


App -> VideoDetail

ใน App.js ใช้งาน <VideoDetail /> และส่ง props ชื่อ video ไปให้

ภาพที่ 35

Video คือ ค่าใน selectedVideo ใน state เป็นค่าวีดีโอที่ถูกคลิกเลือกให้มาแสดงนั้นเอง

ใน VideoDetail.js เรารับค่า video มา มีการตรวจสอบว่า ถ้าไม่มีค่า (null) ก็จะแสดงคำว่า Loading… แทน

ภาพทีี่ 36

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

ภาพที่ 37

สรุป

Components คือส่วนประกอบต่าง ๆ ของโปรเจ็กต์
State คือค่าข้อมูลที่เก็บอยู่ใน components
Props ย่อมาจาก Properties เราใช้มันในการสื่อสารระหว่าง components


ก้าวต่อไป

หลังจากปูพื้นฐานด้วยการทำความเข้าใจคำศัพท์ 3 คำนี้แล้ว ก้าวต่อไปเราจะไปเรียนรู้เรื่องของ Redux ที่จะมาช่วยให้เราจัดการกับ state ได้ง่ายขึ้น

และเรื่อง Hooks ที่จะทำให้เราสร้าง component ในรูปแบบ function แต่สามารถใช้ state หรือใช้ lifecycle ได้

แล้วพบกันใหม่ในบทความต่อไปนะคะ 🙂 Bye!


Sources

Modern React with Redux