ค้นหาเว็บไซต์

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 เล็กๆ (โค้ดตัวอย่าง) ที่สามารถสร้างปัญหาได้ในรูปแบบที่ง่ายขึ้น ปัญหานี้ไม่ปรากฏที่นี่! แต่ยังไม่รู้ว่าทำไมปัญหานี้ยังคงเกิดขึ้นในแอปของเรา ดังนั้นยินดีรับฟีดแบ็กทุกอย่าง!

อาหารว่าง