การจัดการข้อผิดพลาดกับการใช้ react-apollo hook กลายพันธุ์


10

ฉันพยายามที่จะแก้ไขปัญหานี้ แต่ไม่พบคำตอบที่ดี ฉันพยายามที่จะดำเนินการกลายพันธุ์เข้าสู่ระบบโดยใช้ตะขอ useMutation

TLDR; ฉันต้องการที่จะรู้ว่าอะไรคือความแตกต่างระหว่าง onError ผ่านในตัวเลือกและข้อผิดพลาดให้ฉันโดย useMutation

นี่คือข้อมูลโค้ดของฉัน

const [login, { data, loading, error }] = useMutation(LOGIN_QUERY, {
        variables: {
            email,
            password
        },
        onError(err) {
            console.log(err);
        },
});

ฝั่งเซิร์ฟเวอร์ฉันมีอีเมลที่ตั้งไว้ล่วงหน้า / ฮาร์ดโค้ดที่ใช้ในการเข้าสู่ระบบและฉันไม่ได้ใช้ Apollo หรือไคลเอนต์อื่น ๆ ในตัวแก้ไขการเข้าสู่ระบบการกลายพันธุ์นี้ฉันเพียงแค่โยนข้อผิดพลาดหากอีเมลไม่เหมือนกันโดยใช้

throw new Error('Invalid Email');

ตอนนี้ฉันต้องการจัดการข้อผิดพลาดนี้ที่ฝั่งไคลเอ็นต์ (ตอบสนอง) แต่ข้อกังวลของฉันคือว่าถ้าฉันใช้ 'ข้อผิดพลาด' ส่งคืนจากตะขอ useMutation และพยายามที่จะแสดงข้อผิดพลาดด้วยวิธีนี้

render() {
...
{error && <div> Error occured </div>}
...
}

ข้อผิดพลาดได้รับการอัพเดตใน UI แต่ทันทีจะแสดงหน้าจอที่มีการปฏิเสธจัดการ (ข้อผิดพลาด) ทันที: ข้อผิดพลาด Graphql: My-custom-error-message

แต่ถ้าฉันใช้ onError ส่งต่อในตัวเลือกเพื่อใช้ฟังก์ชัน Mutate มันจะไม่แสดงหน้าจอนี้ให้ฉันและฉันสามารถทำอะไรก็ได้ที่ฉันต้องการด้วยข้อผิดพลาด

ฉันต้องการทราบว่าข้อแตกต่างระหว่าง onError ที่ส่งผ่านในตัวเลือกและข้อผิดพลาดที่ฉันได้รับคืออะไรโดย useMutation และทำไม React แสดงหน้าจอข้อผิดพลาดนั้นให้ฉันเมื่อไม่ได้ใช้onError

ขอบคุณ!

คำตอบ:


32

อพอลโล exposes สองชนิดของข้อผิดพลาดที่ผ่าน API ของ: ข้อผิดพลาด GraphQLซึ่งจะกลับมาเป็นส่วนหนึ่งของการตอบสนองเป็นerrorsข้างdataและข้อผิดพลาดของเครือข่ายที่เกิดขึ้นเมื่อมีการร้องขอล้มเหลว ข้อผิดพลาดของเครือข่ายจะเกิดขึ้นเมื่อเซิร์ฟเวอร์ไม่สามารถเข้าถึงหรือหากสถานะการตอบสนองเป็นสิ่งอื่นนอกเหนือจาก 200 - แบบสอบถามที่มีerrorsในการตอบสนองยังสามารถมีสถานะ 200 แต่แบบสอบถามที่ไม่ถูกต้องจะส่งผลให้ สถานะ 400 และข้อผิดพลาดเครือข่ายในลูกค้า Apollo

ลูกค้าอพอลโลให้สี่วิธีที่แตกต่างกันในการจัดการข้อผิดพลาดของการกลายพันธุ์:

1. ) การเรียกmutateฟังก์ชันที่ส่งคืนโดย hook ส่งคืน Promise หากการร้องขอสำเร็จสัญญาจะแก้ไขไปยังวัตถุการตอบสนองที่มีการdataส่งคืนโดยเซิร์ฟเวอร์ หากคำขอล้มเหลวสัญญาจะปฏิเสธพร้อมข้อผิดพลาด นี่คือเหตุผลที่คุณเห็นข้อความ "ปฏิเสธการจัดการ" ในคอนโซล - คุณต้องจัดการกับสัญญาที่ถูกปฏิเสธ

login()
  .then(({ data }) => {
    // you can do something with the response here
  })
  .catch(e => {
    // you can do something with the error here
  })

หรือด้วยไวยากรณ์ async / คอย:

try {
  const { data } = await login()
} catch (e) {
  // do something with the error here
}

โดยค่าเริ่มต้นสัญญาจะปฏิเสธข้อผิดพลาดทั้ง GraphQL หรือข้อผิดพลาดเครือข่าย โดยการตั้งค่าerrorPolicyเป็นignoreหรือallแม้ว่า Promise จะปฏิเสธเฉพาะข้อผิดพลาดของเครือข่าย ในกรณีนี้ข้อผิดพลาด GraphQL จะยังคงสามารถเข้าถึงได้ผ่านวัตถุตอบสนอง แต่สัญญาจะแก้ไข

2. ) ข้อยกเว้นข้างต้นเท่านั้นที่เกิดขึ้นเมื่อคุณจัดเตรียมonErrorฟังก์ชัน ในกรณีนี้สัญญาจะแก้ไขได้เสมอแทนที่จะปฏิเสธ แต่หากมีข้อผิดพลาดเกิดขึ้นonErrorจะถูกเรียกพร้อมกับข้อผิดพลาดที่เกิดขึ้น errorPolicyคุณตั้งใช้ที่นี่เกินไป - onErrorมักจะถูกเรียกว่าสำหรับข้อผิดพลาดของเครือข่าย แต่จะได้รับการเรียกว่ามีข้อผิดพลาด GraphQL เมื่อใช้ค่าเริ่มต้นของerrorPolicy noneการใช้onErrorเทียบเท่ากับการจับสัญญาที่ปฏิเสธ - เพียงแค่ย้ายตัวจัดการข้อผิดพลาดจากไซต์การโทรของmutateฟังก์ชันไปยังไซต์การโทรของ hook

3. ) นอกเหนือจากmutateฟังก์ชั่นแล้วuseMutationฮุกยังส่งคืนผลลัพธ์ผลลัพธ์ด้วย วัตถุนี้ยังเปิดเผยข้อผิดพลาดใด ๆ ที่พบเมื่อใช้การกลายพันธุ์ ซึ่งแตกต่างจากการทำงานที่ผิดพลาดจัดการเราเขียนข้างต้นนี้errorวัตถุที่แสดงให้เห็นถึงสถานะโปรแกรม ทั้งวัตถุerrorและdataสัมผัสด้วยวิธีนี้มีอยู่เป็นความสะดวกสบาย พวกเขาเทียบเท่ากับการทำสิ่งนี้:

const [mutate] = useMutation(YOUR_MUTATION)
const [data, setData] = useState()
const [error, setError] = useState()
const handleClick = async () => {
  try {
    const { data } = await mutate()
    setData(data)
  catch (e) {
    setError(e)
  }
}

การมีสถานะข้อผิดพลาดเช่นนี้จะมีประโยชน์เมื่อคุณต้องการให้ UI ของคุณสะท้อนความจริงว่ามีข้อผิดพลาด ตัวอย่างเช่นคุณอาจเปลี่ยนสีขององค์ประกอบจนกว่าการกลายพันธุ์จะทำงานโดยไม่มีข้อผิดพลาด แทนที่จะต้องเขียนแผ่นสำเร็จรูปด้านบนด้วยตัวคุณเองคุณสามารถใช้วัตถุผลลัพธ์ที่ให้มาได้

const [mutate, { data, error }] = useMutation(YOUR_MUTATION)

หมายเหตุ:ในขณะที่คุณสามารถใช้สถานะข้อผิดพลาดที่เปิดเผยเพื่ออัปเดต UI ของคุณการทำเช่นนั้นไม่ใช่สิ่งทดแทนการจัดการข้อผิดพลาดจริง ๆ คุณต้องระบุการonErrorโทรกลับหรือcatchข้อผิดพลาดเพื่อหลีกเลี่ยงคำเตือนเกี่ยวกับการปฏิเสธสัญญาที่ไม่สามารถจัดการได้

4. ) สุดท้ายคุณสามารถใช้apollo-link-errorเพื่อเพิ่มการจัดการข้อผิดพลาดทั่วโลกสำหรับคำขอของคุณ สิ่งนี้ช่วยให้คุณสามารถแสดงไดอะล็อกข้อผิดพลาดโดยไม่คำนึงว่าคำขอนั้นมาจากที่ใดในแอปพลิเคชันของคุณ

วิธีการใดที่คุณใช้ในแอปพลิเคชันของคุณขึ้นอยู่กับสิ่งที่คุณพยายามทำ (Global vs local, state vs callback และอื่น ๆ ) แอปพลิเคชันส่วนใหญ่จะใช้วิธีการจัดการข้อผิดพลาดมากกว่าหนึ่งวิธี


ขอบคุณสำหรับคำอธิบาย! โหวตแล้ว!
Hyphæne Ohmen
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.