มาทำความรู้จัก React Native และ Flutter กันเถอะ — Part 1: Intro & React Native

Phongharit Pichaiwong
20Scoops CNX
Published in
8 min readOct 28, 2022
Ref: https://cdn-dppbk.nitrocdn.com/yQqYxSaTIazRSTSDbfxPrqFzJPJOhsTG/assets/static/optimized/rev-3378732/wp-content/uploads/2019/06/flutter_blog-react-vs-flutter-1200x640.png.webp

สวัสดีท่านผู้อ่านที่หลงเข้ามากันทุกท่าน วันนี้ตัวผู้เขียนจะขอมาแชร์ความรู้และประสบการณ์ในการพัฒนา mobile application ในรูปแบบของ cross-platform คือ React Native และ Flutter ซึ่งถือว่าเป็นที่นิยมทำกันอย่างมากในปัจจุบัน โดยส่วนตัวผู้เขียนเองมีประสบการณ์ในการพัฒนา application ด้วย React Naitve มากว่า 5 ปี แน่นอนว่ามีความคุ้นชิน (และแอบจะดู bias นิดหน่อย 😂)

ตอนนี้ตัวผู้เขียนเองได้มีโอกาสมาลองศึกษาและพัฒนา application ด้วย Flutter จริงๆจังๆเสียที ถือว่าเป็นโอกาสอันดีที่จะได้เริ่มต้นเขียนบทความเพื่อแชร์และแลกเปลี่ยนความรู้และประสบการณ์ ในด้านการพัฒนา application แบบ cross-platform ด้วย Flutter และ React Native ให้มากขึ้นกว่าเดิม 😉

โดยจะขอแบ่งบทความออกเป็น 3 part นะครับ เพราะไม่งั้นจะยาวจนเกินไป 😂

  • Part 1: React Native
  • Part 2: Flutter
  • Part 3: Comparison (base on 2022)

Intro — อะไรคือ React Native และ Flutter?

React Native และ Flutter คือการพัฒนา application ในรูปแบบของ cross-platform ซึ่งจะมีทั้งส่วนคล้ายและแตกต่างกันออกไปดังนี้

การพัฒนา application แบบ cross-platform คือ การพัฒนา application ให้สามารถทำงานได้บนหลาย platform เช่น สามารถทำงานได้ทั้งบน Android และ iOS ด้วย codebase ชุดเดียวกัน

React Native

เป็น JavaScript Framework (open-source) ที่ถูกสร้างและพัฒนาโดย Facebook (Meta) เปิดตัวครั้งแรก (official release) ที่งาน F8 Conference เมื่อตอนช่วงต้นปี 2015 ที่ผ่านมา โดยภาษาหลักที่ใช้ในการพัฒนาก็คือ JavaScript นั่นเอง

ปัจจุบันนี้นักพัฒนาส่วนใหญ่จะหันมาใช้ TypeScript ในการพัฒนาโปรเจ็ค React Native กันเป็นหลักมากขึ้น (แน่นอนรวมทั้งตัวผมเองด้วย ) ส่วนถ้าถามว่า TypeScript คืออะไร ทำไมเราถึงต้องใช้มัน ก็สามารถตามเข้าไปอ่านได้ในบทความเก่าๆที่ผมเคยเขียนไว้ได้นะครับ (แถมไม่ค่อยมีเวลากลับมาอัพเดตต่อด้วยสิ 😂)

👉🏻 Hello TypeScrip!

ตัวอย่าง application ที่ถูกพัฒนาด้วย React Native

More: Showcase · React Native และ Top 26 Popular Apps Built In React Native| Examples of React Native Apps (spec-india.com)

Architecture Overview

React Native นั้นมีการทำงานแบบ single-threaded (Heavy Weight Process) นั่นคือในแต่ละ process จะมีเพียงแค่ 1 thread เท่านั้น แต่จะมีการทำงานเป็นแบบ multiple processes แทน (ไม่ใช่ multi-threading นะครับ)

Single-threaded means that a process is designed to have only one thread of execution. This means only one set of instructions executes at once.

โดยทั่วไป ในการทำงานของ React Native application จะมี threads หลักๆประกอบไปด้วย

  1. UI Thread (Main Thread): ทำหน้าที่หลักในการจัดการเกี่ยวกับ UI ทั้งบน Android และ iOS เช่น การแสดงผลและอัพเดท UI เมื่อมีการเปลี่ยนแปลง
  2. JavaScript Thread: ทำหน้าที่ในการประมวลผลและจัดการ JS Bundle (JavaScript code ที่ถูก bundled รวมกันเป็นไฟล์เดียว) ซึ่งเป็นส่วนของ logic ต่างๆ เช่น React code และทำงานตาม logic ที่ระบุไว้
  3. Shadow Thread: เป็น background thread ที่ถูกใช้สำหรับประมวลชุดคำสั่งที่เกี่ยวกับ UI ต่อจาก JavaScript Thread เพื่อคำนวนหาตำแหน่งในการจัดวางและจัดการกับ styling ตัว layout ร่วมกับตัว Yoga (Layout engine) ก่อนถูกนำไปแสดงผลผ่านทาง UI Thread
  4. Native Modules Thread: การทำงานในส่วนนี้จะเกิดขึ้นเมื่อตัว application ต้องการเข้าถึงหรือใช้งาน platform API เช่น หากเรากำลังต้องการทำงานเกี่ยว animation เราอาจต้องใช้ native driver เข้ามาช่วยจัดการเป็นต้น
  5. Render Thread: เป็น thread ที่ถูกสร้างขึ้นมาเพื่อใช้ในกรณีเฉพาะ เช่นบน Android L (5.0) เพื่อใช้ในการสร้าง UI ร่วมกับคำสั่งของ OpenGL เป็นต้น

ที่เรียกมันว่า Shadow thread เพราะมันมีการสร้าง shadow nodes (Shadow tree) ขึ้นมานั่นเอง

Old Architecture

ก่อนหน้าที่จะมีการเปลี่ยนมาใช้ architecture แบบใหม่ (RN version ต่ำกว่า 0.68) ตัว React Native จะใช้การติดต่อสื่อสารกันระหว่างฝั่ง JS และ Native ผ่านทาง Bridge โดยจะต้องมีการแปลงข้อมูลในแบบของ JSON (serializing) แล้วนำมาเรียงต่อๆกัน (batched) เพื่อส่งไปยังอีกฝั่งในรูปแบบ “JSON Queue” แบบ asynchronous ซึ่งพออีกฝั่งได้รับก็ต้องนำมา reformat อีกรอบ เพื่อจะนำไปใช้ต่อได้…

ปัญหาที่เจอ ยกตัวอย่างเช่น:

  1. แน่นอนว่าต้องเป็นเรื่องของ performance เพราะด้วยการที่ต้องใช้ Bridg มาเป็นตัวกลางในการสื่อสารระหว่างฝั่ง JS และ Native แทนที่จะสามารถติดต่อกันได้ตรงๆ จึงต้องเสียเวลาในการจัดการ Queue ของ JSON message ที่ส่งไปมา รวมถึงการที่ต้องแปลงข้อมูล (reformat) เพื่ออีกฝั่งนำไปใช้ต่อได้อีก
  2. การมี serializable ที่ bridge ส่งผลให้เกิดการ copy ข้อมูลบางอย่างที่ไม่จำเป็น
  3. การรับ-ส่งข้อมูลที่มีขนาดใหญ่มากๆที่ bridge หาก จะส่งผลกระทบโดยตรงต่อ performance อย่างเลี่ยงไม่ได้
  4. Rendering in React Native is asynchronousยกตัวอย่างเช่น ถ้าเรา render เพื่อ list ของข้อมูลจำนวนมากๆ แล้วทำการ scroll ขึ้นลงอย่างรวดเร็ว เราคงคาดหวังว่าการแสดงผลของ UI กับชุดข้อมูลใน list ลำดับถัดๆไป จะสามารถทำได้อย่างไหลลื่นไม่สะดุด แต่เนื่องจากการ render ของ React Native (และ React) เป็นแบบ asynchronous ดังนั้นจึงจำเป็นต้องรอเวลา เพื่อให้การรับ-ส่งข้อมูลระหว่าง JS และ Native เสร็จสิ้นซะก่อน (แถมเป็นแบบ asynchronous อีกด้วย 😓) ตรงนี้การทำให้เกิดการ delay หรือเกิดการกระตุกขึ้นได้
  5. การรับส่งข้อมูลผ่าน Bridge ในแบบ asynchronous JSON serialization ไม่สามารถรับประกันได้เลยว่า ข้อมูลที่ส่งไปทั้งหมด จะถูกส่งถึงอีกฝั่งอย่างครบถ้วนสมบูรณ์และตรงตามเวลาที่กำหนด
  6. ยิ่งถ้าหากมีการรับ-ส่งข้อมูลผ่านทาง Bridge มากจนเกินไป อาจจะส่งผลกระทบต่อ performance ในการ render โดยตรง (ปัญหาคอขวด)
  7. Native modules บางตัวที่ต้องการการเข้าถึงข้อมูลแบบ synchronous อาจไม่สามารถใช้ประโยชน์จากตรงจุดนี้
  8. JSC (JavaScriptCore) ที่ใช้ประมวลผล JS Bundle ไฟล์ มีอยู่แค่ใน iOS แต่ในส่วนของ Android เอง จำเป็นต้อง bundle รวมเพิ่มเข้าไปในด้วย.. นั่นส่งผลต่อขนาดของ application ที่เพิ่มขึ้นอย่างเลี่ยงไม่ได้

New Architecture

จากข้างต้น เราคงจะพอเห็นถึงปัญหาต่างๆที่เกิดขึ้นจากการตัว architecture แบบเก่า ที่ต้องการอาศัย bridge เป็นตัวกลางในการสื่อสารทั้ง 2 ฝั่ง (JS และ Native) แล้วสินะครับ ดังนั้นทาง Facebook เองจึงได้มีการ “Re-architectureเพื่อให้ได้ solution ที่ดีกว่าเดิม โดยจะมีองค์ประกอบสำคัญเพิ่มเข้ามาแทนที่ bridge นั่นคือ Fabric, JSI, Turbomodules และ Codegen

  1. JavaScript Interface (JSI)

จากเดิมที่การติดต่อสื่อสารระหว่าง 2 ฝั่งต้องทำผ่าน bridge โดยที่จะมีการแปลงข้อมูลเพื่อส่งผ่าน bridge แล้ว reformat เพื่อให้อีกฝั่งนำไปใช้งานได้ต่อ ในตัว architecture แบบใหม่จะกลายมาเป็น

จากแผนภาพข้างบนจะเห็นได้ว่า bridge หายไป และมีตัว JSI (JavaScript Interface) เข้ามาแทนที่ และสิ่งที่ต่างออกไปนอกเหนือจากนั้นก็คือ ภาพการแพ็คของใส่กล่องเพื่อส่งขึ้นรถไปอีกฝั่ง พอถึงอีกฝั่งก็เปิดกล่องออกเพื่อนำไปใช้ก็หายไปด้วย??

นั่นเพราะว่าเจ้า JSI นั้นได้ถูกออกแบบมาเพื่อให้มาใช้แทนการติดต่อสื่อสารผ่านทาง bridge อย่างสมบูรณ์ จุดประสงค์หลักนั่นก็เพื่อให้ทั้งฝั่ง Native และ JS สามารถติดต่อสื่อสารกันได้โดยตรง โดยไม่ต้องมีขั้นตอนที่ยุ่งยากเพิ่มเติมเหมือนตอนที่ใช้ bridge นั่งเอง

“By using JSI, Javascript will be able to hold references to C++ Host objects and invoke methods on them, consequently enabling the Javascript and Native components to recognize and communicate with each other directly”

นั่นคือ JSI จะทำหน้าที่ในการ share reference จากฝั่ง Native (Host Objects) ไปให้ฝั่ง JS สามารถเรียกใช้งาน นั่นหมายความว่าฝั่ง JS จะสามารถเรียกใช้ method จากทางฝั่ง Native ได้โดยตรง แถมไม่ต้องมีการแปลงข้อมูลเป็น JSON เพื่อส่งไปส่งมาเหมือนเก่าอีกด้วย เพราะด้วยความที่ JSI ถูกพัฒนามาด้วยภาษา C++ ทำให้มันสามารถทำงานร่วมกับทั้ง iOS และ Android ได้อย่างไม่มีปัญหานั่นเอง

C++ สำหรับทาง iOS คงไม่ใช้ปัญหา ส่วนทาง Android ก็สามารถสื่อสารกับ C++ ผ่านทาง JNI (Java Native Interface) ได้อยู่แล้ว

“This will eliminate the need to serialize JSON messages and will fix the congestion and asynchronous issues on the bridge.”

ผลที่ตามมาคือ ฝั่ง JS และ Native สามารถติดต่อสื่อสารกันได้โดยตรง แถมยังลดปัญหาความแออัด (คอขวด) รวมไปถึงปัญหาของรูปแบบการรับส่งแบบ asynchronous ตามที่กล่าวมาข้างต้นที่ bridge ได้อีกด้วย

และสิ่งที่เห็นได้ชัดต่อมาก็คือ JS bundle ไม่มีความจำเป็นอีกต่อไป ซึ่งในอนาคตเราอาจสามารถแทนที่ JSC (Javascript Core) ที่ใช้ประมวลผล JS Bundle ได้ด้วย Javascript engine อื่นๆได้อีกด้วย เช่น Chrome Engine V8 เป็นต้น

2. Fabric

มันคือระบบการ Render แบบใหม่ (UI Manager ใหม่) ที่ถูกนำมาใช้แทนของเดิม เอ่อ..แล้วแบบเดิมมันเป็นยังไงหล่ะ?

เพื่อให้เห็นภาพได้ง่ายขึ้น ผมจะลองเขียน code ง่ายๆดังที่เห็นในตัวอย่างทางฝั่งซ้าย เพื่อทำการสร้าง UI ที่ใช้แสดงข้อความออกมา ตามผลลัพธ์ที่เห็นทางด้านฝั่งขวามือนะครับ

กล่าวคือตอนนี้ผมเขียน code ด้วยภาษา JavaScript แต่ทำอย่างไรมันถึงทำให้การแสดงผลบนฝั่ง Native ของทั้ง Android และ iOS เข้าใจ code เหล่านั้นและแสดงผลลัพธ์ออกมาได้เหมือนกันนะ 🤔

ซึ่งองค์ประกอบหลักๆที่เกี่ยวข้องในส่วนนี้จะมี ReactElementTree, ReactShadowTree, HostViewTree และ Yoga

อธิบายคร่าวๆ คือ เวลาที่เรารัน application ตัว React จะทำการ execute โค้ดของเรา เพื่อสร้างเป็น ReactElementTree (JavaScript) และต่อจากนั้น ตัว Renderer ก็จะนำ ReactElementTree ที่ได้ไปสร้างเป็น ReactShadowTree (C++) เพื่อให้ฝั่ง Native สามารถนำไปใช้งานได้ต่อ

แต่ก่อนอื่น ฝั่ง Native จำเป็นต้องทราบก่อนว่า ตัว Native จะต้องกำหนดขนาดและตำแหน่ง layout ของ UI เป็นแบบไหนยังไงบ้าง เพราะฝั่ง Native คงไม่เข้าใจ FlexBox จากทางฝั่ง React อยู่แล้ว

โดยหน้าที่ในการคำนวนหาขนาดและระบุตำแหน่งเพื่อใช้ในการจัดวาง layout จะเป็นหน้าที่ของ Layout Engine ที่มีชื่อว่า “Yoga” โดยตัวมันจะทำการคำนวน เพื่อหาค่าต่างๆออกมาจาก ReactShadowTree ที่ถูกส่งมานั่นเอง

พอได้ค่าต่างๆที่ต้องการเรียบร้อย เช่น style และ content ในแต่ละ view จาก Shadow Tree และผลลัพธ์ที่ได้มาจาก Yoga จากนั้นตัว Shadow Tree ก็จะถูกเปลี่ยนไปเป็น HostViewTree ที่สามราถนำไปใช้แสดงผลเป็น view ต่างๆ ของแต่ละ host platforms (ทั้ง Android และ iOS) ได้ เช่นใน Android เอง HostView จะประกอบไปด้วย ViewGroup จาก android.view.ViewGroup หรือ TextView จาก android.widget.TextView เป็นต้น

ปัญหาที่ตามมาของ Architecture แบบนี้ก็คือ:

  1. Rendering in React Native is asynchronousหรือปัญหาการต้องรอเวลา รับ-ส่ง ข้อมูลระหว่าง JS และ Native ทำให้การทำให้เกิดการ delay หรือเกิดการกระตุกของการแสดงผลได้ (ReactView <=> HostView)
  2. ปัญหาการ copy ข้อมูลซ้ำซ้อนโดยไม่จำเป็น เช่น หากต้องการ render element เช่น <Text /> ก็ต้องมาสร้าง node 2 ชุด คือของ ReactElementTree (JavaScript) และ ReactShadowTree (C++) ซึ่งทั้งคู่ก็คือ <Text /> นี่หล่ะ แถมข้อมูลข้างในก็ถูก copy ซ้ำซ้อนและแยกเก็บไว้ใน node ของตัวเอง ไม่ดีเลยใช่ไหมครับ แทนที่จะสามารถอ้างอิงกันได้ตรงๆโดยไม่ต้องมีการสร้าง node และ duplicate ข้อมูลซ้ำซ้อนโดยไม่จำเป็นแบบนี้
  3. แน่นอนว่า พอเป็นการติดต่อสื่อสารผ่าน bridge เรื่องของ performance ก็ตามมาเช่นกัน

แล้วแบบนี้ Fabric จะเข้ามาแก้ปัญหาได้ยังไงหล่ะ..? 🤔

“Fabric is React Native’s new rendering system, a conceptual evolution of the legacy render system”

จากที่กล่าวมาแล้วข้างต้น ในเมื่อเราเปลี่ยนมาใช้ JSI แทนการสื่อสารผ่านทาง bridge แล้ว มันจึงทำให้ฝั่ง JS สามารถอ้างอิงและเรียกใช้ Native methods ได้ผ่านทาง reference ที่เก็บไว้บน JSI ได้โดยตรง นั่นรวมถึง UI methods ด้วย! ผลลัพธืที่ได้ก็คือ “rendering is synchronous nowนี่เป็นการช่วยแก้ปัญหาเดิมที่มีและเพิ่มประสิทธิภาพในการแสดงผลขึ้นอีกเยอะเลย 🥳

ลองนึกภาพตามตอนที่เรา scolll โดยการลากขึ้น-ลงหรือปัดไป-มา เพื่อ list ของข้อมูลจำนวนมากๆ การประมวลผลและ render ui ของข้อมูลในชุดถัดๆไป จากนี้จะสามารถทำได้เลยแบบ synchronous โดยไม่ต้องรอให้การสื่อสารทั้งสองฝั่งเสร็จก่อนแบบตอน asynchronous อีกแล้ว โดยที่เรายังทำการ fetch ข้อมูลผ่าน API เป็นแบบ asynchronous แยกกันได้อยู่เหมือนเดิม

นอกจากนี้ตัว Renderer ใหม่ยังรองรับ multi-priority และ synchronous events ซึ่งทำให้ตัว Renderer เองสามารถจัดลำดับความสำคัญได้ ว่าควรจะทำการ render synchronous events อันไหนก่อนหลัง เพื่อให้แน่ใจว่าจะสามรถจัดการในส่วนของการแสดงผลลัพธ์ UI ได้อย่างถูกต้องและถูกเวลา

ประโยชน์อื่นๆนอกเหนือจากนี้ เมื่อเราสามรถปลดล็อคเงื่อนไขจากวิธี render แบบเดิมใน architecture อันเก่าได้แล้ว ก็คือการนำเอาทั้ง React Suspense และ Concurrent Features จาก React 18 มาใช้บน React Native เช่น useTransition, useDeferredValue หรือ Suspense API จะทำให้เพิ่มขีดความสามารถในการจัดการ fetch ข้อมูลผ่าน API เพื่อนำมาแสดงผลได้อย่างมีประสิทธิภาพเพิ่มมากขึ้น รวมถึงกาน 🚀

3. Turbo Modules

โดยวัตถุประสงค์หลักของ Turbo modules จะคล้ายๆกับ Native Modules ใน architecture แบบเก่า นั่นคือทำหน้าที่ initialize ตัว Native Modules (อาทิเช่น DeviceInformation, FileStorage เป็นต้น) ตอน startup application

แต่จะต่างกันตรงที่ของเดิมจะทำการโหลด modules มาทั้งหมด เพื่อทำการ initialize โดยไม่สนใจว่า ณ เวลานั้นจำเป็นต้องใช้ตัว modules นั้นๆหรือยัง.. ฟังดูแล้วไม่ค่อยดีเลยใช่ไหมครับ เพราะมันจะต้องส่งผลต่อเวลาในการ startup app ที่มากขึ้นอย่างเลี่ยงไม่ได้รวมไปถึงการจัดการทรัพยากรที่จะได้ได้ไม่ดีเท่าที่ควร เช่น สมมุติว่า app เราต้องใช้ modules ทั้งหมด 20 ตัว แต่ตอนขณะ startu app เราไม่ได้ต้องการใช้งานอะไรจากพวกมันเลยก็ตาม ทำให้เราก็จำเป็นต้องรอให้มันโหลด modules ทุกตัวให้ครบก่อนนั่นหล่ะครับ.. 😓

แต่สำหรับ Turbo modules จะต่างจากแบบเดิมตรงที่มันเป็น “lazy-loaded” นั่นคือมันจะโหลด modules ที่ต้องการก็ต่อเมื่อ app ต้องการใช้งาน modules เหล่านั้นจริงๆเท่านั้นเอง ฟังดูดีขึ้นมากว่าเดิมมากเลยใช่ไหมครับ และที่ทำแบบนั้นได้ก็เพราะตอนนี้เรามี JSI เข้ามาเป็นตัวกลางในการาเก็บ reference อ้างอิงไปยัง modules เหล่านั้นโดยตรงได้แล้ว ทำให้ฝั่ง JS สามารถนำ reference เหล่านั้นไปใช้อ้างอิงไปยัง modules ตัวที่ต้องการได้โดยตรงเลย โดยไม่ต้องเสียเวลามาโหลดทุกๆ modules เก็บไว้ก่อนเหมือนแบบเก่าอีกต่อไป ผลที่ตามตามแน่นอน นอกจากจะเป็นการจัดการทรัพยากรที่ดีขึ้น ยังสามารถช่วยเพิ่มประสิทธิภาพและลดเวลาการ startup app ได้อีกด้วย 😎

4. CodeGen

โดย Concept หลักของ CodeGen หลักนั่นก็เพื่อสิ่งที่เรียกว่า “Type Safety” ขึ้นระหว่างฝั่ง JS และ host platforms เพราะเดิมทีฝั่ง JS และ Native มันมี typed language ที่แตกต่างกันอยู่

อย่างที่หลายท่านคงกันว่า ภาษา JavaScript มันเป็นทั้ง “Dynamic Typing Language” ในขณะที่ JSI ที่ถูกเขียนมาจาก C++ นั้นเป็น “Static Typing Language” แต่ทั้งคู่จะเป็นWeakly Typed Language” แบบเดียวกัน

In static typing, the type is bound to the variable. Types are checked at compile time.

In dynamic typing, the type is bound to the value. The checks are made at runtime.

ดังนั้นจึงจำเป็นต้องมีสิ่งที่เป็น “static type checker” อย่าง CodeGen เข้ามาช่วยตรงนี้ เพื่อให้การทำงานติดต่อสื่อสารกันทั้ง 2 ฝั่งเป็นไปได้อย่างเรียบร้อยและราบรื่น

โดยที่ Codegen จะเข้ามาช่วยทำการ generate โค้ดของตัว C++ structs ที่ใช้ในการเก็บ porps โดย props ทั้งหมดจะอ้างอิงมาจาก JavaScript component ที่ถูกส่งเข้ามาและจะถูกใช้เพื่อเป็น “Source Of Truth” ในการสร้าง C++ structs จาก Codegen นั่นเอง

ดังนั้น หากมีความไม่ตรงกันระหว่าง JavaScript และ host component props เกิดขึ้น ก็จะทำให้เกิด build error หรือ compile-time error แทนที่จะเป็น runtime error นั่นเอง

5. Lean Core

อีกส่วนสุดท้ายของการทำ re-architecture ใน React Native ครั้งนี้นั่นก็คือ “Lean Core” โดยจุดประสงค์ของมันก็คือ “แยกส่วนและลดขนาด” เพื่อทำให้ repository หลักของ React Native มีขนาดเบาลงให้มากที่สุด เพื่อที่จะง่ายต่อการ maintain ทั้งโดยทางฝั่ง Facebook เองและทางฝั่ง community ด้วย โดยการแยก Native Modules ที่ไม่เกี่ยวกับ core หลักออกไปเก็บไว้ที่ repository อื่นๆแทน แล้วให้ทาง developer ติดตั้งหากต้องการใช้งานเองทีหลัง

ตัวอย่าง Native Modules ที่แยกออกไปเช่น ImageStore, PushNotificationIOS, AsyncStorage, ProgressBarAndroid, Picker and PickerIOS, ReactART เป็นต้น

ประโยชน์สำหรับทาง community เช่น พอ repository ของ core หลักมีขนาดเล็กลง ก็ช่วยทำให้เวลาการ pull requests เร็วขึ้นได้ และช่วยลดปัญหาที่เกิดจาก library ที่ outdated แล้วหรือไม่มีการพัฒนาต่อได้อีกทาง ทางฝั่ง library ที่แยกออกไปก็จะปล่อยให้ทาง community เข้ามาดูแลจัดการกันเองได้ทันที โดยไม่ต้องรอหรือพึ่งแต่ทาง Facebook พัฒนาและแก้ไขปัญหาที่เกิดอยู่ฝั่งเดียว

แถมพอได้ทำการแยก library/modules ที่ไม่จำเป็นออกจาก core หลักแล้ว ก็ส่งผลให้ตัว generated app มีขนาดลดลงตามไปด้วยนั่นเอง 🚀

Life Cycle

สำหรับ React Native application นั้น เราจะมองว่าทุกอย่างเกิดจากรวมกันของส่วนประกอบย่อยที่เรียกว่า “Component” เช่น ใน UI หน้าหนึ่งเกิดจากการนำเอา component ย่อยต่างๆหลายตัวมารวมกัน ซึ่งในแต่ละ component อาจทำหน้าที่เป็นได้ทั้งแบบที่มีใช้สำหรับการแสดงผลบนหน้าจออย่างเดียว (presentational) หรือแบบมีทั้ง business logic และสามารถแสดงผลพร้อมกันในตัว (container)

ดังนั้นการที่พูดเกี่ยวกับ LifeCycle ของ React Native ก็จะเป็นทำความเข้าใจถึงกระบวนการ สร้าง (creation) — เปลี่ยนแปลง (updating) — และทำลาย (destroy) ของตัว component หรือที่เรียกว่า “Component Lifecycle”

โดยหลักๆแล้ว Component Lifecycle ใน React Native จะสามารถแบ่งได้ออกเป็น 4 เฟส กล่าวโดยสรุปคร่าวๆคือ

  1. Mounting: จะเป็นเฟสที่มีการสร้างตัว component instance และใส่เข้าไปใน DOM (Document Object Model)
  2. Updating: จะเป็นเฟสที่มีการจัดการเกี่ยวกับการ update component เมื่อพบว่าค่า props หรือ state ของ component นั้นๆมีการเปลี่ยนแปลงเกิดขึ้น โดยจะทำการ re-render ตัว component นั้นใหม่ เพื่อให้เกิดการเปลี่ยนแปลงตามค่าที่เปลี่ยนไป
  3. Unmounting: เป็นเฟสที่จะทำการลบหรือทำลายตัว react component ออกจาก “Actual DOM”
  4. Error Handling: เป็นเฟสที่ทำหน้าที่จัดการเกี่ยว error ต่างๆที่เกิดขึ้น ในขณะที่มีการ render component

ทั้งนี้ยังมีรายละเอียดปลีกย่อยที่สำคัญและน่าสนใจอีกมากมาย อย่างเช่น “React Hook” ว่ามันคืออะไร เกี่ยวข้องยังไงกับ React Lifecycle แล้ว Class Component กับ Functional Component เหมือนหรือต่างกันยังไง บลา..บลา..บลา แต่เกรงว่าบทความนี้จะยิ่งยาวออกๆไปเรื่อยๆ 😅 ก็ขอขายตรงเลยละกัน ฝากเข้าไปติดตามอ่านกันได้จากบทความ (ของน้องในทีมผมเอง) จาก link ด้านล่างนี้ได้เลยครับ

👉🏻 React Component Lifecycle คืออะไร? มีการทำการเป็นอย่างไงและเมื่อไรที่เราควรต้องใช้มัน | 20Scoops CNX (medium.com)

ตัวอย่าง Tools สำหรับการพัฒนาด้วย React Native

  1. Visual Studio Code
  2. Flipper
  3. React Native Debugger
  4. Expo / React Native CLI
  5. Android Studio
  6. Xcode
  7. Reactotron
  8. State Management: Redux, MobX, Zustand, Jotai และอื่นๆ

ตัวอย่าง Code

ส่งท้าย

จากที่เกริ่นร่ายยาวข้างต้นมาทั้งหมด (ตอนแรกว่าจะเขียนนิดเดียวพอเป็นพิธี 😅) น่าจะทำให้ผู้อ่านหลายท่านพอเข้าใจพื้นฐานและองค์ประกอบหลักๆในการพัฒนาด้วย React Native กันบ้างไม่มากก็น้อย หวังว่าจะพอเป็นประโยชน์กับท่านผู้ที่หลงเข้ามาอ่านกันทุกๆท่านนะครับ 😊

Happy Eating! (Coding มาทั้งวันละ หิว!!)

Reference:

--

--

Phongharit Pichaiwong
20Scoops CNX

Team Lead — Senior Mobile (Native Android and React Native), Blockchain and Full Stack Developer.