Flux คืออะไร ? + สอนวิธีนำไปใช้กับ React

วันนี้ SiamHTML จะขอพูดถึงแนวทางการเขียน JavaScript แบบใหม่ที่มีชื่อเรียกว่า Flux ครับ แต่อย่าเพิ่งตกใจนะครับว่า Flux นั้นเป็น JavaScript framework ตัวใหม่ที่เราจะต้องมาเรียนรู้กันอีก เพราะจริงๆ แล้วมันก็เป็นแค่ “pattern” หรือ “architecture” ของการเขียนโค้ดเท่านั้นเอง เรียกว่าคล้ายๆ กับการที่เราเขียนโค้ดโดยยึดหลัก MVC นั่นแหละครับ เรามาดูกันว่า Flux นั้นจะช่วยให้การเขียนโค้ดของเราดีขึ้นได้มากแค่ไหน ?

ปกติเราเขียน React กันอย่างไร ?

จากบทความก่อนหน้านี้ ที่ SiamHTML ได้เล่าถึงการทำเว็บแบบ Isomorphic ด้วย React นั้น หากสังเกตดีๆ จะเห็นว่ามันเป็นแค่แอปแบบง่ายๆ เท่านั้นเอง ถูกมั้ยครับ ? เรียกว่าแทบจะไม่มี logic อะไรเลย ทีนี้ถ้าเราจะทำแอปกันจริงๆ มี logic ซับซ้อนยิ่งขึ้น มีการดึงข้อมูลมาจากฐานข้อมูล ถามว่าโค้ด logic พวกนี้ เราควรจะเขียนไว้ที่ไหน ? ภายใน component งั้นหรอ ? ไม่ดีแน่ๆ ครับ

รู้จักกับ Flux

ลองนึกเล่นๆ นะครับว่า ถ้าเราเอา application logic ไปกองไว้ตาม component ต่างๆ เราจะลำบากแค่ไหน debug ก็ยาก เขียน test ก็ยาก แถมยัง reuse ไม่ได้อีก เพื่อเป็นการแก้ปัญหาเหล่านี้ วิศวกรของ facebook เค้าจึงคิดค้น Flux ขึ้นมาครับ

อย่างที่บอกนะครับว่า Flux นั้นเป็นแค่ pattern ของการเขียนโค้ดเท่านั้นเอง ซึ่งหมายความว่าตัวมันเองไม่ได้มีไฟล์อะไรเลย มันเป็นแค่ “แนวคิด” ที่ทีม facebook เค้าใช้ในการเขียน React เพื่อช่วยให้การทำงานเป็นไปอย่างราบรื่นเท่านั้นเอง

ผมขอทวนก่อนนะครับว่า React นั้นมี data flow แบบ Unidirectional ซึ่งก็คือระบบที่ข้อมูลจะไหลไปในทิศทางเดียว Flux นั้นก็เหมือนกันครับ เพียงแต่มันจะมีการกำหนดการ flow ของข้อมูลให้มีระบบมากขึ้น เราลองมาดูกันคร่าวๆ นะครับว่า data flow ของ Flux นั้นมีหน้าตาเป็นอย่างไร

flux simple diagram

เห็นมั้ยครับว่าการ flow ของข้อมูลนั้นจะเป็นแบบทางเดียว คือจะเริ่มจากการมี Action ขึ้นมาก่อน จากนั้นก็จะส่งข้อมูลต่อไปยัง Dispatcher และ Store ตามลำดับ และสุดท้ายข้อมูลก็จะถูกส่งไปถึง View ครับ

แต่ในความเป็นจริงแล้ว เว็บแอปส่วนใหญ่มักจะมี interaction กับ user ถูกมั้ยครับ ดังนั้น ตัว View เอง ก็สามารถทำให้เกิด Action ขึ้นมาได้เช่นกันครับ data flow จริงๆ จึงจะเปลี่ยนเป็นแบบนี้

flux diagram

ก่อนจะไปต่อ ผมขอแนะนำให้จำ diagram นี้ให้ขึ้นใจเลยนะครับ แต่ตอนนี้เราอาจจะยังงงๆ อยู่ว่า แล้วแต่ละตัวมันคืออะไร ? เดี๋ยวผมจะไล่อธิบายให้ฟังทีละตัวเลยครับ

เจาะลึก Data Flow ของ Flux

เอาล่ะครับ เรามาดูกันว่า data flow ของ Flux นั้นประกอบไปด้วยอะไรบ้าง

Action

Action ก็คือสิ่งที่เกิดขึ้นเมื่อมี user มาทำอะไรบางอย่างกับ View ครับ (หรือเราจะสั่งให้เกิด Action ขึ้นมาเองเลยก็ได้) สมมติหน้าเว็บเรามีกล่องค้นหาข้อมูลอยู่อันหนึ่ง เมื่อใดก็ตามที่ user กดปุ่ม submit ฟอร์มค้นหา เมื่อนั้นจะมี Action เกิดขึ้นมาครับ แน่นอนว่าข้อมูลที่เราอยากจะผูกไปพร้อมกับ Action นี้ก็คือ keyword ที่ user เค้ากรอกมา ถูกมั้ยครับ คำถามคือ แล้วเราจะส่ง keyword ที่ว่านี้ ไปยังโค้ดส่วนที่จะทำหน้าที่ query ข้อมูลจากฐานข้อมูลได้อย่างไร ?

Dispatcher

วิธีที่ Flux ใช้ก็คือการนำสิ่งที่เรียกว่า Dispatcher มาเป็นตัวกลางครับ โดย Action ดังกล่าวจะต้องไปบอก Dispatcher ว่า 1) ตัวเองคือ Action ประเภทไหน และ 2) มีข้อมูลอะไรที่จะพ่วงมากับ Action นี้บ้าง จากนั้น Dispatcher จะรับหน้าที่ดูว่า Action ดังกล่าว ควรจะวิ่งไปทางไหนต่อครับ

Store

Store คือ ที่ๆ เราจะเก็บข้อมูลต่างๆ ของแอป รวมไปถึง state เอาไว้ครับ นอกจากข้อมูลต่างๆ แล้ว ภายใน Store ก็จะมีการเก็บ method ต่างๆ ที่จะใช้ในการจัดการกับข้อมูลภายใน Store เอาไว้ด้วย หรือพูดง่ายๆ ก็คือมันเป็นที่ๆ เราจะเขียน application logic ต่างๆ นั่นเองครับ อย่างในกรณีนี้ Store จะต้องรับหน้าที่นำ keyword ที่ user กรอกมา ไป query ข้อมูลในฐานข้อมูล แล้วนำผลลัพธ์ที่ได้ ส่งต่อไปยัง View เพื่อแสดงผล แต่แอปเราจะรู้ได้อย่างไรว่า method ไหนใน Store ที่จะต้องจับคู่กับ Action ที่เข้ามาหา ?

คำตอบคือเราจะต้องนำ method ต่างๆ ใน Store ไป register ไว้กับ Dispatcher ก่อนครับ พูดง่ายๆ ก็คือ เราจะต้องจับคู่นั่นเองว่า ถ้ามี Action แบบนี้เข้ามา จะให้วิ่งไปใช้ method ตัวไหน สมมติว่ามี Action ที่ต้องการจะ query ข้อมูลจากฐานข้อมูลเข้ามา เราก็จะต้องจับคู่ Action นี้ เข้ากับ method ที่จะทำหน้าที่เชื่อมต่อกับฐานข้อมูลอะไรทำนองนี้ครับ เมื่อได้ข้อมูลที่ต้องการมาแล้ว Store ก็จะอัพเดทข้อมูลต่างๆ รวมไปถึง state ที่ตัวเองดูแลอยู่ แล้วก็แจ้งกลับไปยัง View เพื่อร้องขอให้มีการ render ใหม่

View

เมื่อ View ได้รับคำร้องขอจาก Store แล้ว View ก็จะไปดึงข้อมูลที่จะต้องใช้ในการ render ใหม่ มาจาก Store จากนั้น View ก็จะ render ตัวเอง และ component ลูกๆ ที่อยู่ภายใน View นั้นๆ ครับ

Workshop – ทำแอป Discussion

มาถึงตรงนี้ หากใครยังงงๆ ก็ขอบอกเลยว่าเป็นเรื่องปกติครับ แนะนำให้อ่านด้านบนเพื่อทบทวนอีกรอบ เพราะตัวผมเองกว่าจะเข้าใจ Flux อย่างละเอียดก็ล่อไปเป็นเดือนเลยเหมือนกัน ของอย่างนี้มันต้องลงมือทำเลยถึงจะเข้าใจครับ ผมว่าเรามาลองเขียนแอปด้วย Flux กันเลยดีกว่า

สมมติว่าโจทย์ของเราคือการสร้างระบบ Discussion แบบง่ายๆ คือเราจะมีฟอร์มอันนึง ให้คนเข้ามา comment อะไรก็ได้ ลองดูซิว่า requirement แบบนี้ เราจะต้องเขียนโค้ดอย่างไร ?

1. เตรียมไฟล์และจัดโครงสร้าง

เริ่มด้วยการสร้างไฟล์และโฟลเดอร์ตามด้านล่างนี้ก่อนเลยครับ

ก็ลองดูคร่าวๆ กันก่อนนะครับว่าแต่ละไฟล์แต่ละโฟลเดอร์นั้นมีหน้าที่เก็บอะไร จากนั้นก็ให้เราไล่ใส่โค้ดตามด้านล่างนี้ต่อได้เลยครับ

index.html

สังเกตนะครับว่าใน body ของเราจะต้องมี #app อยู่ด้วย เพราะเราจะต้องหาที่เอาไว้ render แอปของเราครับ ส่วนก่อนปิด body เราก็จะต้องใส่ script เข้ามาตัวนึง ซึ่งมันก็คือไฟล์ที่ได้จากการรวม script ทั้งหมดของแอปเรานั่นเองครับ

gulpfile.js

ในบทความนี้ ผมจะขอใช้ browserify ในการทำ bundle นะครับ ให้เราเลือก entry point เป็น app.js ได้เลย แล้วตั้งชื่อไฟล์ output ให้เป็น bundle.js ครับ

2. สร้าง Component ต่างๆ แบบ Static

ทีนี้เราจะมาเริ่มสร้าง component กันเลยครับ โดยผมจะขอเริ่มจาก component ที่อยู่นอกสุดก่อนละกัน

DiscussionApp.jsx

ให้เราสร้างไฟล์ใหม่ขึ้นมาอันนึง แล้วตั้งชื่อว่า DiscussionApp.jsx ครับ จากนั้นก็ใส่โค้ดเริ่มต้นตามด้านล่างนี้ลงไป

ผมมองว่าแอป Discussion นี้ ประกอบไปด้วย 2 ส่วนหลักๆ ก็คือ 1) ส่วนของฟอร์มที่จะเอาไว้พิมพ์ comment และ 2) ส่วนที่จะเอาไว้แสดง comment ผมเลยจะขอแยก 2 ส่วนนี้ ออกมาเป็น component ลูก ของ DiscussionApp ครับ

DiscussionForm.jsx

ทีนี้มาดูที่ component ลูก อย่าง DiscussionForm กันบ้างครับ ให้เราใส่โค้ดสำหรับ render ฟอร์มธรรมดาๆ ตามด้านล่างนี้ลงไป

DiscussionList.jsx

มาต่อกันที่ component ลูกอีกตัวอย่าง DiscussionList ที่เราจะเอาไว้แสดง comment ครับ ให้เราใส่โค้ดตามนี้ไปได้เลย

จากโค้ดจะเห็นว่า DiscussionList จะรับ props ที่ชื่อ comments มาวนลูปเพื่อแสดงข้อมูล comment โดยใช้ component ลูกอีกตัว ที่ชื่อ DiscussionComment ครับ คือขอแค่ส่ง props ที่ชื่อ comments มาเหอะ แล้ว DiscussionList จะแสดงข้อมูลออกมาให้เอง

app.js

สุดท้ายเรามาดูที่ไฟล์ entry point ของเรา อย่าง app.js กันบ้างครับ ให้เราใส่โค้ดสำหรับ render DiscussionApp เข้าไปใน #app แบบนี้

มาถึงตรงนี้ โครงของแอปเราเริ่มจะโอเคแล้วล่ะครับ ที่เหลือก็แค่ทำฟอร์มให้สามารถรับข้อมูล comment ได้จริง แล้วก็นำข้อมูลมา assign ให้ DiscussionList เท่านั้นเอง

3. ใส่ Interaction ด้วย State

ทีนี้เราจะมาทำแอปของเราให้ใช้งานได้จริงครับ จาก requirement เราจะเห็นว่าข้อมูลที่จะ flow ไปตามส่วนต่างๆ ของแอปนี้ก็คือ comment ถูกมั้ยครับ ? ซึ่ง comment เหล่านี้จะถูกสร้างขึ้นมาจาก DiscussionForm แล้วจึงถูกนำไปแสดงที่ DiscussionList อีกที หากเป็นแบบนี้ เราจะต้องเก็บ comment เอาไว้ใน state ของ component ตัวแม่ ซึ่งก็คือ DiscussionApp ครับ เพราะมันจะทำให้ DiscussionList สามารถนำ comment ที่สร้างโดย DiscussionForm ไปใช้ได้ด้วย เพื่อให้เห็นภาพมากขึ้นเรามาเริ่มเขียนโค้ดกันเลยดีกว่าครับ

DiscussionApp.jsx

เริ่มกันที่ component ตัวแม่ก่อนเลยครับ ให้เราเพิ่ม method getInitialState() และ _addComment() เข้าไปแบบนี้

ไฮไลท์นั้นจะอยู่ที่การส่ง method _addComment() ไปให้ DiscussionForm ใช้ ผ่าน props ที่ชื่อ handleSubmit ครับ ที่เราต้องใช้ท่านี้ในการเซฟ comment ก็เพราะว่าหากเราให้ DiscussionForm เป็นคนเซฟ comment จากการ submit ลง state ซะเอง เราจะไม่สามารถนำ state นั้น ออกมาใช้ข้างนอก DiscussionForm เพื่อส่งต่อไปยัง DiscussionList ได้นั่นเอง

DiscussionForm.jsx

เอาล่ะครับ เมื่อได้รับ method _addComment() มาจาก component แม่แล้ว มาดูว่าเราจะเอาไปใช้ใน DiscussionForm อย่างไร ?

เมื่อไล่โค้ดดู ก็จะเห็นว่าเราเรียกใช้ method _addComment() ผ่าน props ที่ชื่อ handleSubmit ครับ เพียงเท่านี้ เราก็จะสามารถเซฟ message ที่เกิดขึ้นภายใน DiscussionForm ไปเก็บไว้เป็น state ของ DiscussionApp ได้แล้วล่ะครับ

มาถึงตอนนี้ก็ลองรันดูเลยครับ ให้เราลองพิมพ์ comment อะไรก็ได้ แล้วลอง submit ดู เราก็จะเห็นว่าแอปของเรานั้นทำงานได้แล้ว แต่ช้าก่อน… นี่ยังไม่ใช่วิธีที่ถูกต้อง !

ถึงแม้ว่าแอปของเราจะใช้งานได้แล้วก็จริง แต่การกอง application logic รวมกันไว้ใน component นั้นไม่ดีแน่นอนครับ ไม่ว่าจะเป็นเรื่องของการ debug โค้ด การ reuse โค้ด รวมไปถึงการ test โค้ด แล้วที่สำคัญก็คือ สิ่งที่เก็บไว้ใน state นั้น ควรจะเป็นแค่ข้อมูลเล็กๆ ที่จะเอาไว้บรรยายถึง “สภาพ” ของ component ในขณะนั้นว่าเป็นอย่างไร ไม่ใช่เอา state ไปเก็บข้อมูลที่จะนำมาแสดงผลแบบที่เราทำอยู่ในตอนนี้

4. เปลี่ยนมาใช้ Flux

เพื่อเป็นการแก้ปัญหาดังกล่าว เราจะลองเปลี่ยนมาเขียนตามแนวคิดของ Flux ดูบ้างครับ

4.1 สร้าง Dispatcher ขึ้นมาก่อน

สำหรับ data flow แบบ Flux แล้ว Dispatcher นั้นถือเป็นศูนย์กลางของข้อมูลเลยนะครับ เพราะมันจะต้องคอยดูว่าถ้ามี Action เข้ามาแบบนี้ จะต้องส่งต่อไปยัง method ไหนใน Store สำหรับโค้ดในส่วนของ Dispatcher นั้น เราไม่ต้องไปเขียนเองนะครับ เพราะ Flux เค้าได้เตรียมมาให้เรียบร้อยแล้ว สิ่งที่เราต้องทำก็แค่ติดตั้ง Flux ผ่าน npm แบบนี้ครับ

จากนั้นก็ให้เราสร้างไฟล์ชื่อ AppDispatcher.js ขึ้นมา แล้วใส่โค้ดเรียกใช้ Dispatcher จาก Flux ลงไป

เพียงเท่านี้ เราก็จะได้ความสามารถของ Dispatcher จาก Flux มาใช้แล้วล่ะครับ ให้เราเอาไฟล์นี้ไปวางไว้ในโฟลเดอร์ dispatcher ได้เลย

4.2 ดูว่ามี Action ประเภทไหนบ้าง ?

จากนั้นให้เราลิสต์มาให้หมดครับว่า แอปของเรามีประเภทของ Action หรือ actionType อะไรบ้าง จากตัวอย่างก่อนหน้านี้ เราจะมีเพียงแค่ Action เดียว ซึ่งก็คือ Action ที่เอาไว้เซฟ comment ถูกมั้ยครับ ให้เราสร้างไฟล์ DiscussionConstants.js ขึ้นมา แล้วใส่โค้ดด้านล่างนี้ลงไป

โค้ดด้านบนจะเป็นการบอกว่าแอปนี้ มี actionType ที่ชื่อ DISCUSSION_CREATE เพียงแค่อันเดียวครับ หากเราทำแอปที่ซับซ้อนกว่านี้ ก็ให้เราเพิ่ม actionType ต่อท้ายเข้าไปได้เลย ส่วนสาเหตุที่เราต้องเก็บประเภทของ Action เอาไว้เป็น constant แบบนี้ ก็เพราะว่าเราจะใช้มันในการจับคู่ Action เข้ากับ method ของ Store นั่นเองครับ

4.3 สร้าง Action ขึ้นมา

จากนั้นเราจะมาสร้างตัว Action จริงๆ กันครับ โดยเราจะอาศัย Dispatcher ในการส่ง parameter ที่จำเป็นเข้าไปให้ Store และอาศัย actionType เพื่อเอาไว้บอก Dispatcher ว่า Action นี้ ควรจะจับคู่กับ Store ตัวไหน

4.4 ย้าย Logic มาไว้ใน Store + ผูก Method ของ Store เข้ากับ Action

ทีนี้มาดูที่ Store กันบ้างครับ ให้เราย้าย application logic มาเขียนเป็น method ต่างๆ ของ Store แทน จากนั้นก็ใส่โค้ดสำหรับจับคู่ method เหล่านั้นเข้ากับ actionType ประเภทต่างๆ ครับ

4.5 ลบ Logic เดิมออก แล้วเปลี่ยนมาใช้ Action แทน

จากนั้นกลับมาดูที่ DiscussionForm ในส่วนของ method _onSubmit() นิดนึงครับ ให้เราเปลี่ยนจากการเซฟ comment ด้วย this.props.handleSubmit() มาเป็นการใช้ Action ที่เราสร้างขึ้นมาแทน

4.6 เชื่อม Component หลัก เข้ากับ Store

สุดท้ายแล้ว เราจะต้องเปิดการเชื่อมต่อระหว่าง DiscussionApp กับ Store ครับ ให้เราแก้ไฟล์ DiscussionApp.js ตามโค้ดด้านล่างนี้ได้เลย

จากนั้นก็ลองรันดูอีกทีเลยครับ จะเห็นว่าแอปเรายังคงสามารถทำงานได้ตามเดิม เพียงแต่โค้ดมันจะเป็นระเบียบมากขึ้นเยอะครับ คือ component ก็จะมีแต่ template อย่างเดียว ไม่มี application logic มาแทรกอยู่ด้วยแล้ว

5. ดึงข้อมูลจาก API

ถึงแม้ว่าแอปเราจะทำงานได้แล้วก็จริง แต่มันก็ยังไม่ค่อยจะสมบูรณ์เท่าไรนะครับ เพราะเวลารีเฟรช พวก comment ต่างๆ ที่เคยพิมพ์ไว้มันจะหายไปหมดเลย เราจะแก้ปัญหานี้ด้วยการนำฐานข้อมูลมาใช้ครับ ทุกครั้งที่มีการ comment เราจะต้องเซฟข้อมูล comment นั้นๆ ลงไปในฐานข้อมูลด้วยเสมอ แล้วตอนที่โหลดแอปมาครั้งแรก ก็ให้เราไปดึง comment ทั้งหมดจากฐานข้อมูลมาแสดง ส่วนวิธีการติดต่อกับฐานข้อมูลนั้น ผมแนะนำให้ทำผ่าน API ครับ

คำถามต่อมาก็คือ แล้วเราจะเอาโค้ดส่วนที่เรียกใช้ API ไปไว้ที่ไหน ? ประเด็นนี้ยังคงเป็นที่ถกเถียงกันอยู่พอสมควรเลยนะครับ แต่ส่วนตัวผมขอแนะนำให้เอาไว้ที่ Action แล้วกัน เพราะรู้สึกว่ามันจะไล่โค้ดได้ง่ายกว่าการเอาไว้ใน Store ครับ เพื่อให้เห็นภาพมากขึ้น เรามาลองเขียนโค้ดต่อยอดจากแอปเดิมกันเลย

5.1  เพิ่ม actionType

เริ่มด้วยการเพิ่ม actionType ให้กับ Action สำหรับการดึงข้อมูลจากฐานข้อมูลมาแสดงก่อนเลยครับ ให้เราเข้าไปเพิ่มได้ที่ DiscussionConstants.js

แต่จะเห็นว่านอกจาก DISCUSSION_REQUEST แล้ว ผมยังเพิ่ม DISCUSSION_LOADING เข้ามาด้วยนะครับ เราจะใช้ actionType นี้แหละ ในการบอกว่าแอปกำลังอยู่ในสถานะโหลดข้อมูลอยู่

5.2 เพิ่ม Action สำหรับดึงข้อมูลจาก API

เมื่อได้ actionType มาแล้ว เรามาสร้างตัว Action จริงๆ กันเลยครับ ให้เราเพิ่ม method getComments() เข้ามา แล้วก็ปรับ method addComment() เล็กน้อย ตามนี้ครับ

ไฮไลท์นั้นอยู่ที่ method getComments() ครับ จะเห็นว่ามาถึงเราจะ dispatch DISCUSSION_LOADING ไปก่อนเลย จากนั้นเราจะเริ่มส่ง ajax request ไปยัง API เพื่อขอข้อมูล comment เมื่อได้รับข้อมูลมาแล้ว เราถึงจะ dispatch DISCUSSION_REQUEST เพื่อส่งข้อมูล comment ที่ได้มาจาก API ไปให้ Store ครับ

ส่วน method addComment() ก็จะคล้ายๆ กันครับ เพียงแต่ตอนส่ง ajax request นั้น เราไม่จำเป็นต้องใส่ callback function อะไรเลยก็ได้ เพราะเราจะใช้วิธี optimistic อยู่แล้ว (คือจะแสดงข้อมูลออกมาทางหน้าจอทันที โดยที่ไม่สนว่าข้อมูลนั้นจะถูกเซฟลงฐานข้อมูลเสร็จแล้วหรือยัง)

5.3 สร้าง Method แล้วจับคู่เข้ากับ actionType

จากนั้นเรามาเพิ่ม method ที่ Store กันครับว่าจะให้ทำอะไรกับข้อมูลที่ได้มา

ก่อนอื่นให้เราเปลี่ยนค่าเริ่มต้นของ _state ให้มีการเก็บสถานะ loading ก่อน เราจะได้รู้ว่าตอนนี้แอปกำลังโหลดข้อมูลอยู่หรือเปล่า ส่วนอีกค่านึงที่ต้องเก็บลง _state ก็คือ page ซึ่งเราจะเอาไว้บอกแอปว่าจะต้องไปดึง comment หน้าที่เท่าไรมา

เสร็จแล้วเราจะต้องเพิ่ม private method ที่ชื่อ parseData() เข้ามาครับ เราจะใช้ method นี้ล่ะ ในการรวมร่าง comment ที่โหลดมาก่อนหน้าเข้ากับ comment ที่เพิ่งโหลดมาใหม่ รวมไปถึงการอัพเดทค่า page ที่อยู่ใน _state ด้วย เพื่อเป็นการบอกแอปให้คราวหน้าไปดึงข้อมูลของหน้าถัดไปนั่นเองครับ

เมื่อ method พร้อมแล้ว ทีนี้เราต้องมาจับคู่ให้มันครับ ให้เราจับคู่ DISCUSSION_REQUEST เข้ากับ parseData() ได้เลย จะเห็นว่าผมต้องไปกำหนด loading ให้กลับมาเป็น false เหมือนเดิมด้วยนะครับ เพราะ DISCUSSION_LOADING ที่ถูก dispatch มาก่อนจะเซท loading เป็น true ไว้

5.4 เรียกใช้ Action ที่ View

เนื่องจากผมอยากให้มาถึงก็โหลด comment ล่าสุดมาจากฐานข้อมูลเลย ผมเลยจะขอให้มันไปเรียก getComments() ในตอนที่ componentDidMount เลยละกัน จากนั้นผมก็จะขอเพิ่ม button เข้ามาอันนึง เพื่อเอาไว้กดดู comment เพิ่มเติม เวลามี comment เยอะๆ ครับ จะเห็นว่าปุ่มนี้มันก็ไปเรียก getComments() เหมือนตอนที่ componentDidMount นั่นแหละ เพียงแต่ comment ที่ได้มานั้นจะเป็นของหน้าถัดไปแล้ว เพราะเราจะมีการอัพเดท page ใหม่ทุกครั้งที่โหลด comment เข้ามานั่นเองครับ

สังเกตนิดนึงนะครับว่าผมจะมีการเช็คค่า loading ที่อยู่ใน state ด้วย เพราะถ้าแอปกำลังโหลดข้อมูลอยู่ ผมอยากจะให้มันแสดง feedback อะไรบางอย่างให้ user ได้รับรู้

จากนั้นก็รันดูเลยครับ ให้เราลอง comment ดูเยอะๆ แล้วลองเทสปุ่มโหลด comment เพิ่มเติมดู comment จะต้องแสดงต่อเนื่องกันไปอย่างถูกต้องครับ แล้วที่สำคัญก็คือ เมื่อรีเฟรชแล้ว comment จะต้องไม่หายไปหมดเหมือนในตอนแรก เสร็จแล้วครับ! แอป Discussion ของเรา

ความรู้สึกหลังใช้ Flux

อย่างที่บอกนะครับว่า การทำความเข้าใจ Flux  นั้น อาจจะต้องใช้เวลานิดนึง แต่ผมรับรองว่าคุ้มค่าแน่นอนครับ การแยกโค้ดออกเป็นส่วนๆ นั้น ถึงแม้ว่าอาจจะดูยุ่งยากในตอนแรกที่เห็น แต่เชื่อเถอะครับว่าพอคล่องๆ แล้ว เราจะจำ pattern ได้เอง แล้วอะไรๆ มันจะง่ายขึ้นเยอะเลยล่ะครับ

การเขียนแอปโดยใช้ Flux นั้น ทำให้โค้ดมีระเบียบ แยกออกจากกันอย่างชัดเจนมากขึ้นครับ ประโยชน์ที่เห็นได้ชัดๆ เลยก็คือ มันจะช่วยทำให้การไล่โค้ดง่ายขึ้นกว่าเดิมมาก แล้วยิ่งแอปเรามีคนเขียนร่วมกันหลายคน การใช้ Flux นั้นจะช่วยให้เราสามารถแบ่งงานกันได้ง่ายขึ้นด้วยนะครับ เราอาจแบ่งให้คนนึงรับผิดชอบในส่วนของ component และ action ไปเลย ส่วนอีกคนก็อาจจะดูในส่วนของ store ไป อะไรทำนองนี้ครับ

ผมเคยลองแก้แอปที่เดิมเขียนด้วย jQuery ธรรมดา มาเป็น React + Flux นะครับ ความรู้สึกหลังเขียนเสร็จก็คือ การใช้ React + Flux มันเขียนสนุกกว่าอะครับ มาถึงเราก็แค่จัดเตรียม ui ที่เราอยากจะให้ render ณ state ต่างๆ เอาไว้ ที่เหลือเราก็แค่เล่นกับข้อมูลเท่านั้นเองครับ เราไม่ต้องไปสนว่ามันจะเกิดอะไรขึ้นเมื่อข้อมูลมีการเปลี่ยนแปลง ขอแค่ข้อมูลมันถูก แอปของเราก็จะแสดงผลได้อย่างถูกต้องโดยอัตโนมัติครับ

แนวทางศึกษาต่อ

ก่อนจากกัน ผมอยากจะบอกว่า มันอาจจะไม่จบแค่ Flux นะครับ เพราะในปัจจุบัน มีหลายๆ เจ้า นำไอเดียของ Flux ไปต่อยอดให้มันดีขึ้น มีฟีเจอร์เยอะขึ้น ลดความยุ่งยากซับซ้อนลง โดยตัวที่ผมแนะนำให้ลองไปเล่นดูก็จะมี Alt และ Redux ครับ Alt นี่จะได้ในเรื่องของ docs ที่โอเค และมีคนใช้งานจริงใน production แล้ว ส่วน Redux นั้นน่าสนใจตรงที่มันเพิ่งเกิดใหม่ได้ไม่นาน ทำให้เห็นแนวคิดของ library อื่นๆ หมดแล้วว่าแต่ละเจ้านั้นมีข้อดีข้อเสียยังไง คิดว่าน่าจะใช้เวลาเรียนรู้ไม่นานมากครับ เพราะวิธีคิดนั้นไม่ได้ต่างจาก Flux มากมายอะไร

หากมองดีๆ เราจะเห็นนะครับว่า จริงๆ แล้ว Flux มันไม่ได้ยึดติดอยู่กับ tool หรือ framework ตัวไหนเลย เพราะมันเป็นก็เพียงแค่แนวคิดเท่านั้นเอง นั่นหมายความว่าในอนาคต เราอาจจะเห็นการใช้ Flux ร่วมกับ Angular ก็เป็นได้ ก็คิดซะว่าบทความนี้เป็นการปูพื้นฐานเกี่ยวกับ Flux แล้วกันนะครับ แล้วพบกันใหม่บทความหน้าครับ

(Visited 13,231 times, 8 visits today)

8 Responses to “Flux คืออะไร ? + สอนวิธีนำไปใช้กับ React”

  1. ขอบคุณมากๆ ครับ บทความดีมากๆ
    กำลังใช้ Flux ของ alt อยู่เลย
    งงๆ เรื่อง คอนเซ็ป store แต่ตอนนี้เข้าใจ เพราะบทความนี้เลย

  2. เห้อ!! ผมตามเทคโนโลยีไม่ทันแล้ว ช่วยผมด้วย!!!

  3. ยอดเยี่ยมครับ ขอบคุณสำหรับบทความดีๆ ครับ

  4. รบกวนนิดนึงคราวหลังขอ package.json ด้วยนะครับ 555 ขี้เกียจไล่ลง กำลังลองทำตาม ขอบคุณครับ

  5. {
    "name": "myflux",
    "version": "1.0.0",
    "description": "",
    "main": "gulpfile.js",
    "scripts": {
    "test": ""
    },
    "author": "",
    "license": "ISC",
    "devDependencies": {
    "browserify": "^10.2.4",
    "flux": "^2.0.3",
    "gulp": "^3.9.0",
    "gulp-streamify": "0.0.5",
    "gulp-uglify": "^1.2.0",
    "react": "^0.13.3",
    "reactify": "^1.1.1",
    "vinyl-source-stream": "^1.1.0"
    }
    }

  6. กว่าจะเข้าใจได้ ใช้เวลาเกือบเดือนเหมือนกันครับ ขอบคุณพี่เต้ครับผม

  7. กว่าจะเข้าใจได้ ใช้เวลาเกือบเดือนเหมือนกันครับ ขอบคุณพี่เต้ครับผม

Leave a Reply