คำนำ
โปรแกรมเมอร์หลายๆ ท่านน่าจะเคยพบปัญหาเรื่อง useMutation หลังใช้งานไปสักพักว่าแบบไหนคือรูปแบบที่ถูกต้องสำหรับเวลานำไปใช้งาน เพราะว่า React Query ก็ค่อนข้างหยืดหยุ่น เปิดโอกาสให้ผู้ใช้สามารถใช้งานได้หลายรูปแบบ
Q1: ทำไมเราถึงควรใช้ Axios + React Query มากกว่าการใช้งาน Axios อย่างเดียว ?
Request State Tracking
ถ้าดูจากรูปภาพด้านบนจะเห็นว่า useMutation ได้เตรียมตัวแปรที่เราสามารถเรียกใช้งานได้ในการ Tracking State ตัวอย่างเช่น isLoading ที่เราสามารถใช้ในการแสดงผลของ Loading Indicator และมันยัง Update แบบ Realtime ด้วย เราจึงไม่จำเป็นต้องทำการจัดการโดยใช้ useState เลย
Mutation Lifecycle
useMutation ได้มี Lifecycle ในแต่ละช่วงจังหวะของการ Call API ตั้งแต่ step ก่อนเริ่มยันจบ เราสามารถใช้งาน Callback เหล่านี้ในการ Handle Case ต่าง ๆ ได้มากมาย เช่นการทำ Optimistic update
Q2: POST Request ควรใช้งานกับ useQuery หรือ useMutation?
ความเข้าใจผิดของคนส่วนมากคือคิดว่า Post Request ต้องใช้งานกับ useMutation เท่านั้น แต่จริง ๆ เราสามารถใช้งานกับ useQuery ได้เช่นกัน โดยหลักการคือถ้าเวลาเราเรียก API แล้ว มันเป็นแค่การ Fetch ข้อมูลเฉย ๆ ไม่ได้ทำการแก้ไขข้อมูลใด ๆ ที่ Server กรณีนี้เราควรใช้ useQuery (โดยไม่ต้องคำนึงถึงว่ามันคือ GET หรือ POST)
สิ่งต่าง ๆ ที่ควรรู้เวลาใช้งาน useMutation
การ mutations ข้อมูลจาก queries
ในบางครั้งเราสามารถทำการแก้ไขค่าข้อมูลที่เราได้ทำการ Cache มาก่อนหน้านี้ได้ โดยการแก้ไขค่า จะมีอยู่ 2 วิธี
- Invalidation
จากตัวอย่างด้านบนมีการใช้งาน useQuery() ที่เป็น Custom Hook อยู่และ Reuse ใช้ใน 3 Components ซึ่งกรณีเราต้องการ Fetch ข้อมูลใหม่ เราสามารถใช้งาน refrech() ได้ แต่ในกรณีข้างบนการใช้งาน refetch() ไม่ใช้วิธีที่ถูกต้อง เพราะเราต้อง Contain Logic ในการ refetch() ทั้ง 3 Componentes เลย
กรณีถ้าเรารู้อยู่แล้วว่าหลังจากที่เรา Add ข้อมูลบางอย่างลงใน DB เสร็จ เราต้องการให้
useQeury()
ที่เรามีการ Cache ข้อมูลไว้ Reset เราสามารถใช้คำสั่งในการ invalidateQuery() ซึ่งจะทำให้ Code ดู Clean ขึ้น
- Direct updates
ในบางครั้ง เราไม่ต้องการ Refetch ข้อมูล เพราะว่า Response ที่เราได้รับมามีข้อมูลที่ต้องการใช้ครบถ้วนแล้ว เราสามารถใช้งานคำสั่ง setQueryData() โดยการ Set Value เข้าไปใน queryKey ที่กำหนดได้
Awaited Promises
ถ้าเราต้องการให้ isLoading ยังคงสถานะเป็น
loading อยู่จนกว่า
invalidateQueries
จะทำงานเสร็จ เราจะต้องทำการ return Promise ไปด้วยตามตัวอย่างด้านบน
Mutate or MutateAsync
กรณีเคสทั่วๆ ไป เราควรใช้งาน mutate() เพราะว่า Function นี้จะมี Life Cycle ต่าง ๆ ที่เราสามารถใช้งานได้ เช่น onSuccess , onError
เป็นต้น
กรณีที่ใช้งาน mutateAsync() เราต้องทำการ Handle Error ด้วยตัวเอง และเหมาะกับการใช้ในกรณีที่ เราต้องการ Call หลาย ๆ Mutation พร้อมกันและรอข้อมูลทั้งหมด Return กลับมาก่อนดำเนินการต่อ
อีกกรณีคือ เราต้องการใช้ Response ที่ได้จาก Request แรกที่เรา Call API เป็น Params ในการเรียก API ตัวถัดไป การใช้งาน mutateAsync() จะช่วยลดการเกิด Callback Hell ได้
Some Callbacks Might Not Fire
โดยปกติแล้ว Callback จะไม่ถูก Trigger ถ้า Component ได้ถูก Unmount ไปก่อนแล้ว
ถ้าเรามี Logic ที่ถูกใช้งานในลักษณะ Common ไม่ว่า Component ไหนที่เรียก useMutation() นี้ก็จะทำเหมือนกัน (เช่น invalidation) เราควรใส่ Logic นั้นไว้ที่ useMutation
Callback
ถ้าเรามี Logic ในลักษณะเฉพาะ ที่เกี่ยวข้องกับ UI เช่นการ Redirect หรือการแสดง Notification เราควรใส่ไว้ที่ Mutate Callback ของแต่ละ Component
พูดคุยเกี่ยวกับเรียนรู้การใช้งาน useMutation จาก React Query และเพิ่มประสิทธิภาพในการพัฒนา! ทีม IT Consulting ของเราพร้อมเสนอคำแนะนำที่เหมาะกับธุรกิจของคุณ
References: 1, 2, 3