คำถามที่จะตัดสินใจเลือก State Stack ของคุณ
เลิกเปรียบเทียบ Redux กับ React Query ได้แล้ว
มันเหมือนกับการถามว่าคุณอยากได้ค้อนหรือไขควง ทั้งที่คุณยังไม่รู้เลยว่าจะสร้างอะไร Redux, React Query และ Zustand ต่างก็แก้ปัญหาที่แตกต่างกัน
การตัดสินใจที่แท้จริงมาจากคำถามเพียงข้อเดียว: ใครคือเจ้าของ "แหล่งข้อมูลที่ถูกต้อง" (source of truth) สำหรับ state แต่ละตัว?
คุณมี "ความจริง" อยู่สองประเภท
- Owned Truth Client คือแหล่งข้อมูล ซึ่งรวมถึงสิ่งต่างๆ เช่น:
- Sidebar เปิดอยู่หรือไม่?
- Theme ปัจจุบันคืออะไร?
- ฟอร์มอยู่ในขั้นตอนไหน? State เหล่านี้ขึ้นอยู่กับการตัดสินใจภายในเครื่อง (local) ของคุณ ไม่จำเป็นต้องไปตรวจสอบซ้ำกับเซิร์ฟเวอร์
- Borrowed Truth แหล่งข้อมูลอยู่ที่เซิร์ฟเวอร์ Client เป็นเพียงผู้ถือข้อมูลที่สะท้อนมาจากเซิร์ฟเวอร์เท่านั้น ข้อมูลนี้สามารถเปลี่ยนแปลงได้ตลอดเวลาโดยที่คุณไม่รู้ตัว หน้าที่ของคุณคือการจัดการ:
- ความล้าสมัยของข้อมูล (Staleness)
- การยกเลิกความถูกต้อง (Invalidation)
- การดึงข้อมูลใหม่ (Refetching)
- การทำแคช (Caching)
นักพัฒนาส่วนใหญ่ประสบปัญหาเพราะใช้เครื่องมือเพียงอย่างเดียวจัดการทั้งสองอย่าง เมื่อคุณพยายามจัดการ Borrowed Truth ใน client-side reducer คุณจะลงเอยด้วยการเขียน React Query ซ้ำในแบบที่ไม่มีประสิทธิภาพ คุณต้องเขียนสถานะการโหลด (loading states), การจัดการข้อผิดพลาด (error handling) และการทำแคช (caching) ด้วยตัวเอง ซึ่งทำให้เกิดโค้ดที่ไม่จำเป็นจำนวนมหาศาล
แยกพวกมันออกจากกันเพื่อชัยชนะ
ใช้ React Query สำหรับ borrowed truth เพราะมันจัดการงานซิงโครไนซ์ที่ยากลำบากให้คุณแล้ว ใช้ Zustand สำหรับ owned truth เพราะมันจัดการการเก็บค่าแบบง่ายๆ โดยไม่มีขั้นตอนที่ยุ่งยาก (zero ceremony)
อย่าเอาข้อมูลจากเซิร์ฟเวอร์ไปใส่ไว้ใน Zustand จงรักษาขอบเขตนั้นให้ชัดเจน
แล้ว Redux กับ Sagas ล่ะ? Sagas ไม่ได้มีไว้สำหรับดึงข้อมูล (data fetching) แต่มีไว้เพื่อจัดการกระบวนการที่ซับซ้อนที่เกิดขึ้นต่อเนื่องตามเวลา ใช้พวกมันหากแอปของคุณต้องจัดการกับ:
- Flow ที่ทำงานพร้อมกันและสามารถยกเลิกได้ (Concurrent, cancellable flows)
- ข้อมูลแบบ Real-time websocket streams
- State machines ที่ซับซ้อน
ถ้าคุณใช้ React Query แล้ว Sagas ของคุณไม่ได้ทำอะไรเลย คุณก็ไม่จำเป็นต้องใช้มัน
ยังมีทางเลือกที่สาม: การรวมเป็นหนึ่ง (Unification) RTK Query และ Redux ช่วยให้คุณเก็บทุกอย่างไว้ใน store เดียวกัน ทำให้คุณเห็นภาพรวม (snapshot) ของทั้งแอปได้ในที่เดียว ซึ่งช่วยให้การทำ debugging, การ logout และการทำ offline persistence ง่ายขึ้นมาก
เลือกเส้นทางของคุณตามความต้องการ:
- React Query + Zustand: เหมาะที่สุดสำหรับทีมขนาดเล็กที่ต้องการความซับซ้อนต่ำ
- Redux + Sagas: เหมาะที่สุดสำหรับโดเมนที่มีการทำงานพร้อมกันสูง (high-concurrency) เช่น แอปเทรดหุ้น
- RTK Only: เหมาะที่สุดสำหรับทีมระดับองค์กรขนาดใหญ่ที่ต้องการแหล่งข้อมูลที่ถูกต้องเพียงหนึ่งเดียว (single source of truth)
ก่อนจะเลือกเครื่องมือ ให้ถามตัวเองก่อนว่า state นั้นจำเป็นต้องอยู่ที่ client จริงๆ หรือไม่ เพราะ Server Components กำลังย้ายตรรกะเหล่านี้กลับไปไว้ที่เซิร์ฟเวอร์มากขึ้น
หาให้เจอก่อนว่าใครคือเจ้าของความจริง แล้วเครื่องมือที่เหมาะสมจะตามมาเอง