Choosing an Approach
การตัดสินใจ ให้ง่าย
หัวข้อที่มีชื่อว่า “การตัดสินใจ ให้ง่าย”ตอนนี้คุณรู้กลไกแล้ว การเลือกใช้ส่วนใหญ่เป็นเรื่องของ scope และความซับซ้อน และเดินตาม decision path สั้น ๆ:
flowchart TB
q1{"มี widget มากกว่าหนึ่งตัว
ที่ต้องการ state นี้ไหม?"} -->|ไม่| ss["setState
(ephemeral / local)"]
q1 -->|ใช่| q2{"flow ซับซ้อน,
app ใหญ่, ต้อง test สูงไหม?"}
q2 -->|ไม่| prov["Provider / Riverpod
(shared app state)"]
q2 -->|ใช่| bloc["BLoC / Cubit
(unidirectional, test ได้)"] - widget เดียวสน?
setStateอย่าเพิ่ม package เพื่อ checkbox - หลาย widget share? Provider หรือ Riverpod Riverpod สำหรับ app ใหม่/ใหญ่
- ซับซ้อน, async หนัก, ต้อง test แยกได้? BLoC/Cubit
ไม่มีรางวัลสำหรับการใช้เครื่องมือที่หนักที่สุด app จริงผสมทั้งสามได้อย่างสบาย: setState สำหรับ UI ชิ้นเล็ก, Riverpod provider สองสามตัวสำหรับ shared state, และ BLoC เฉพาะที่ความซับซ้อนสมควรจริง ๆ
Lifting state up
หัวข้อที่มีชื่อว่า “Lifting state up”เมื่อ sibling widget สองตัวต้องการ state เดียวกัน ให้ย้าย state ขึ้นไปไว้ที่ common ancestor ที่ใกล้ที่สุดแล้วส่งลงมา — lifting state up นี่คือสิ่งแรกที่ควรลองก่อนหยิบ shared-state package ใด ๆ
| สถานการณ์ | state ควรอยู่ที่ไหน |
|---|---|
| widget เดียวใช้ | ใน widget นั้น (setState) |
| sibling สองตัว share | lift ไปที่ parent ร่วม |
| หลาย widget ทั่ว tree | store ที่ share (Provider/Riverpod) |
| ทั้ง app, ซับซ้อน, async | layer BLoC/Cubit |
Ephemeral vs app state และการ layer
หัวข้อที่มีชื่อว่า “Ephemeral vs app state และการ layer”นิสัยที่สำคัญที่สุดคือการจัดหมวด state ให้ถูก:
- Ephemeral state — index ของ
PageView, form field, animation อยู่ในStateหายไปตอน rebuild ก็ไม่เป็นไร - App state — auth, cart, settings, cached server data share และมักถูก persist อยู่ใน store นอก widget ตัวใดตัวหนึ่ง
สำหรับอะไรที่เกิน app เล่น ๆ layer หน้าที่พวกนี้เพื่อไม่ให้พันกัน:
- UI layer — widget render state, ส่ง input ไม่มี business logic
- State/logic layer — provider, BLoC, notifier ถือและ transition state
- Data layer — repository และ service คุยกับ API, database, device
การเก็บ business logic และ data access ออกจาก widget คือสิ่งที่ทำให้ app test ได้และรอดเมื่อ app โตขึ้น — ไม่ว่าจะเลือก state package ตัวไหน