typescript - Apollo การเรียก refetch จะไม่ส่งคำขอหลังจากเกิดข้อผิดพลาดเครือข่าย
บริบท
ปัจจุบันเรากำลังพัฒนาแอป iOS ด้วย React Native พร้อมกับ back-end ของ Graphql ภายในแอปนี้ เราต้องการแสดง modal ให้ผู้ใช้เมื่อไม่มีการเชื่อมต่ออินเทอร์เน็ตหรือเมื่อ API ใช้งานไม่ได้
เนื่องจากเราใช้ Apollo และ graphql-code-generator เราจึงมี hook ที่สร้างขึ้นในคอมโพเนนต์เพื่อดึงข้อมูล เราจะแสดง modal เมื่อ hook ส่งคืนข้อผิดพลาดเครือข่าย หากพบข้อผิดพลาดเครือข่าย จะใช้เมธอด refetch จาก hook เพื่อทำการ polling และตรวจสอบว่าเครือข่ายหรือ API กลับมาใช้งานได้หรือไม่
ปัญหา
น่าเสียดายที่สิ่งนี้ดูเหมือนไม่ได้ผล การเรียกใช้เมธอด refetch หลังจากที่การเชื่อมต่อเครือข่ายกลับมาใหม่ไม่ได้ก่อให้เกิดคำขอ เมธอด refetch ยังทำให้เกิดข้อผิดพลาดเครือข่ายด้วย
รหัส
function useConnectionStatusPolling() {
// 'useData' is a custom wrapper around the generated hook, that maps and deserialises fields.
const { loading, refetch, error } = useData();
// While refreshing, error.networkError is reset.But we would like
// to keep the error status around until the request works again.
//
// For that, we keep the error in the mutable reference, and update it
// only when the status it not loading. For loading, keep the
// previous value.
const networkError = useRef(false);
if (!loading) {
networkError.current = !!error?.networkError;
}
// Polling is done manually via useInterval because the builtin polling stops
// if a network error is thrown which we want to ignore in our case.
useInterval(refetch, networkError.current ? 5000 : "pause");
return networkError.current;
}
/**
* Executes a callback at each interval.
* https://overreacted.io/making-setinterval-declarative-with-react-hooks/
* @param callback Method to execute after each delay.
* @param delay Time in miliseconds.
*/
export function useInterval(callback: () => void, delay: number | "pause") {
const savedCallback = useRef<() => void>();
// Remember the latest callback.
useEffect(() => {
savedCallback.current = callback;
}, [callback]);
// Set up the interval.
useEffect(() => {
function tick() {
savedCallback.current?.();
}
if (delay !== "pause") {
const id = setInterval(tick, delay);
return () => clearInterval(id);
}
}, [delay]);
}
การวิจัยและความพยายาม
เราพบว่าข้อผิดพลาดไม่ได้ถูกลบตามที่ระบุในบทความนี้ ดังนั้น hook นี้จะยังคงแสดงโมดอลไม่มีอินเทอร์เน็ตและทำการขอข้อมูล อย่างไรก็ตามปัญหานี้ยังคงมีอยู่หลังจากการเปลี่ยนแปลงนี้ วิธี refetch เพียงแค่ไม่ทำการขอข้อมูลไปยัง API เรายังได้ลองล้างแคชแล้ว แต่ไม่มีประโยชน์ น่าเสียดาย ดังนั้นตอนนี้ฉันไม่แน่ใจว่าจะลองทำอะไรเพื่อให้มันทำงานได้ คำแนะนำใด ๆ จะได้รับการชื่นชมอย่างมาก!
แก้ไข
สร้างตัวอย่างขนม Expo เล็กๆ (โค้ดตัวอย่าง) ที่สามารถสร้างปัญหาได้ในรูปแบบที่ง่ายขึ้น ปัญหานี้ไม่ปรากฏที่นี่! แต่ยังไม่รู้ว่าทำไมปัญหานี้ยังคงเกิดขึ้นในแอปของเรา ดังนั้นยินดีรับฟีดแบ็กทุกอย่าง!
อาหารว่าง