เชี่ยวชาญ React Suspense และ Error Boundaries เพื่อการจัดการสถานะการโหลดที่แข็งแกร่งและการจัดการข้อผิดพลาดที่สง่างาม เรียนรู้วิธีสร้างแอปพลิเคชันที่ยืดหยุ่นและใช้งานง่าย
React Suspense และ Error Boundaries: การจัดการการโหลดและการจัดการข้อผิดพลาดขั้นสูง
React Suspense และ Error Boundaries เป็นคุณสมบัติที่มีประสิทธิภาพที่ช่วยให้นักพัฒนาสร้างแอปพลิเคชันที่ยืดหยุ่นและใช้งานง่ายยิ่งขึ้น โดยมีวิธีประกาศในการจัดการสถานะการโหลดและข้อผิดพลาดที่ไม่คาดคิด ปรับปรุงประสบการณ์ผู้ใช้โดยรวม และลดความซับซ้อนของกระบวนการพัฒนา บทความนี้ให้คำแนะนำที่ครอบคลุมเกี่ยวกับการใช้ React Suspense และ Error Boundaries อย่างมีประสิทธิภาพ ครอบคลุมทุกอย่างตั้งแต่แนวคิดพื้นฐานไปจนถึงเทคนิคขั้นสูง
ทำความเข้าใจกับ React Suspense
React Suspense เป็นกลไกสำหรับ "ระงับ" การแสดงผลของส่วนประกอบจนกว่าจะเป็นไปตามเงื่อนไขที่ระบุ โดยทั่วไปคือความพร้อมใช้งานของข้อมูลจากการดำเนินการแบบอะซิงโครนัส ซึ่งช่วยให้คุณแสดง UI สำรอง เช่น ตัวบ่งชี้การโหลด ในขณะที่รอให้โหลดข้อมูล Suspense ช่วยลดความซับซ้อนในการจัดการสถานะการโหลด ขจัดความจำเป็นในการแสดงผลตามเงื่อนไขด้วยตนเอง และปรับปรุงความสามารถในการอ่านโค้ด
แนวคิดหลักของ Suspense
- Suspense Boundaries: นี่คือส่วนประกอบ React ที่ครอบส่วนประกอบที่อาจระงับ กำหนด UI สำรองที่จะแสดงในขณะที่ส่วนประกอบที่ครอบถูกระงับ
- Fallback UI: UI ที่แสดงในขณะที่ส่วนประกอบถูกระงับ โดยทั่วไปแล้วจะเป็นตัวบ่งชี้การโหลดหรือตัวยึดตำแหน่ง
- Asynchronous Data Fetching: Suspense ทำงานได้อย่างราบรื่นกับไลบรารีการดึงข้อมูลแบบอะซิงโครนัส เช่น `fetch`, `axios` หรือโซลูชันการดึงข้อมูลแบบกำหนดเอง
- Code Splitting: Suspense ยังสามารถใช้เพื่อหน่วงเวลาการโหลดโมดูลโค้ด ทำให้สามารถแยกโค้ดและปรับปรุงประสิทธิภาพการโหลดหน้าเว็บเริ่มต้นได้
การใช้งาน Suspense ขั้นพื้นฐาน
นี่คือตัวอย่างง่ายๆ เกี่ยวกับวิธีใช้ Suspense เพื่อแสดงตัวบ่งชี้การโหลดขณะดึงข้อมูล:
import React, { Suspense } from 'react';
// จำลองการดึงข้อมูล (เช่น จาก API)
const fetchData = () => {
return new Promise((resolve) => {
setTimeout(() => {
resolve({ name: 'John Doe', age: 30 });
}, 2000);
});
};
// สร้างทรัพยากรที่ Suspense สามารถใช้ได้
const createResource = (promise) => {
let status = 'pending';
let result;
let suspender = promise().then(
(r) => {
status = 'success';
result = r;
},
(e) => {
status = 'error';
result = e;
}
);
return {
read() {
if (status === 'pending') {
throw suspender;
} else if (status === 'error') {
throw result;
}
return result;
},
};
};
const userData = createResource(fetchData);
// ส่วนประกอบที่อ่านจากทรัพยากร
const UserProfile = () => {
const data = userData.read();
return (
Name: {data.name}
Age: {data.age}
);
};
const App = () => {
return (
Loading user data...
ในตัวอย่างนี้:
- `fetchData` จำลองการดำเนินการดึงข้อมูลแบบอะซิงโครนัส
- `createResource` สร้างทรัพยากรที่ Suspense สามารถใช้เพื่อติดตามสถานะการโหลดของข้อมูล
- `UserProfile` อ่านข้อมูลจากทรัพยากรโดยใช้วิธี `read` หากข้อมูลยังไม่พร้อมใช้งาน ระบบจะส่งคืน Promise ซึ่งจะระงับส่วนประกอบ
- ส่วนประกอบ `Suspense` ครอบ `UserProfile` และให้ `fallback` prop ซึ่งระบุ UI ที่จะแสดงในขณะที่ส่วนประกอบถูกระงับ
Suspense กับ Code Splitting
Suspense ยังสามารถใช้กับ React.lazy เพื่อใช้การแยกโค้ดได้ ซึ่งช่วยให้คุณโหลดส่วนประกอบเฉพาะเมื่อจำเป็น ปรับปรุงประสิทธิภาพการโหลดหน้าเว็บเริ่มต้น
import React, { Suspense, lazy } from 'react';
// Lazy load ส่วนประกอบ MyComponent
const MyComponent = lazy(() => import('./MyComponent'));
const App = () => {
return (
Loading component...}>
);
};
export default App;
ในตัวอย่างนี้:
- `React.lazy` ใช้เพื่อโหลดส่วนประกอบ `MyComponent` แบบ Lazy
- ส่วนประกอบ `Suspense` ครอบ `MyComponent` และให้ `fallback` prop ซึ่งระบุ UI ที่จะแสดงในขณะที่ส่วนประกอบกำลังโหลด
ทำความเข้าใจกับ Error Boundaries
Error Boundaries เป็นส่วนประกอบ React ที่ตรวจจับข้อผิดพลาด JavaScript ที่ใดก็ได้ในแผนผังส่วนประกอบลูก บันทึกข้อผิดพลาดเหล่านั้น และแสดง UI สำรองแทนที่จะทำให้แอปพลิเคชันทั้งหมดหยุดทำงาน มีวิธีจัดการข้อผิดพลาดที่ไม่คาดคิดอย่างสง่างาม ปรับปรุงประสบการณ์ผู้ใช้ และทำให้แอปพลิเคชันของคุณแข็งแกร่งยิ่งขึ้น
แนวคิดหลักของ Error Boundaries
- Error Catching: Error Boundaries ตรวจจับข้อผิดพลาดระหว่างการแสดงผล ในเมธอด Lifecycle และใน Constructors ของแผนผังทั้งหมดด้านล่าง
- Fallback UI: UI ที่แสดงเมื่อเกิดข้อผิดพลาด โดยทั่วไปแล้วจะเป็นข้อความแสดงข้อผิดพลาดหรือตัวยึดตำแหน่ง
- Error Logging: Error Boundaries ช่วยให้คุณสามารถบันทึกข้อผิดพลาดไปยังบริการหรือคอนโซลเพื่อวัตถุประสงค์ในการแก้ไขข้อบกพร่องได้
- Component Tree Isolation: Error Boundaries แยกข้อผิดพลาดไปยังส่วนเฉพาะของแผนผังส่วนประกอบ ป้องกันไม่ให้ข้อผิดพลาดเหล่านั้นทำให้แอปพลิเคชันทั้งหมดหยุดทำงาน
การใช้งาน Error Boundaries ขั้นพื้นฐาน
นี่คือตัวอย่างง่ายๆ เกี่ยวกับวิธีสร้าง Error Boundary:
import React, { Component } from 'react';
class ErrorBoundary extends Component {
constructor(props) {
super(props);
this.state = { hasError: false };
}
static getDerivedStateFromError(error) {
// อัปเดตสถานะเพื่อให้การแสดงผลครั้งถัดไปแสดง UI สำรอง
return { hasError: true };
}
componentDidCatch(error, errorInfo) {
// คุณยังสามารถบันทึกข้อผิดพลาดไปยังบริการรายงานข้อผิดพลาดได้
console.error(error, errorInfo);
}
render() {
if (this.state.hasError) {
// คุณสามารถแสดง UI สำรองแบบกำหนดเองได้
return Something went wrong.
;
}
return this.props.children;
}
}
export default ErrorBoundary;
ในตัวอย่างนี้:
- ส่วนประกอบ `ErrorBoundary` กำหนดเมธอด `getDerivedStateFromError` และ `componentDidCatch`
- `getDerivedStateFromError` จะถูกเรียกเมื่อเกิดข้อผิดพลาดในส่วนประกอบลูก อัปเดตสถานะเพื่อระบุว่าเกิดข้อผิดพลาดแล้ว
- `componentDidCatch` จะถูกเรียกหลังจากตรวจพบข้อผิดพลาดแล้ว ช่วยให้คุณสามารถบันทึกข้อผิดพลาดไปยังบริการหรือคอนโซลได้
- เมธอด `render` จะตรวจสอบสถานะ `hasError` และแสดง UI สำรองหากเกิดข้อผิดพลาด
การใช้ Error Boundaries
ในการใช้ส่วนประกอบ `ErrorBoundary` เพียงแค่ครอบส่วนประกอบที่คุณต้องการป้องกันด้วยส่วนประกอบนั้น:
import React from 'react';
import ErrorBoundary from './ErrorBoundary';
const MyComponent = () => {
// จำลองข้อผิดพลาด
throw new Error('An error occurred!');
};
const App = () => {
return (
);
};
export default App;
ในตัวอย่างนี้ หากเกิดข้อผิดพลาดใน `MyComponent` ส่วนประกอบ `ErrorBoundary` จะตรวจจับข้อผิดพลาดและแสดง UI สำรอง
การรวม Suspense และ Error Boundaries
Suspense และ Error Boundaries สามารถรวมกันเพื่อมอบกลยุทธ์การจัดการข้อผิดพลาดที่แข็งแกร่งและครอบคลุมสำหรับการดำเนินการแบบอะซิงโครนัส โดยการครอบส่วนประกอบที่อาจระงับด้วย Suspense และ Error Boundaries คุณสามารถจัดการทั้งสถานะการโหลดและข้อผิดพลาดที่ไม่คาดคิดได้อย่างสง่างาม
ตัวอย่างการรวม Suspense และ Error Boundaries
import React, { Suspense } from 'react';
import ErrorBoundary from './ErrorBoundary';
// จำลองการดึงข้อมูล (เช่น จาก API)
const fetchData = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
// จำลองการดึงข้อมูลสำเร็จ
// resolve({ name: 'John Doe', age: 30 });
// จำลองข้อผิดพลาดระหว่างการดึงข้อมูล
reject(new Error('Failed to fetch user data'));
}, 2000);
});
};
// สร้างทรัพยากรที่ Suspense สามารถใช้ได้
const createResource = (promise) => {
let status = 'pending';
let result;
let suspender = promise().then(
(r) => {
status = 'success';
result = r;
},
(e) => {
status = 'error';
result = e;
}
);
return {
read() {
if (status === 'pending') {
throw suspender;
} else if (status === 'error') {
throw result;
}
return result;
},
};
};
const userData = createResource(fetchData);
// ส่วนประกอบที่อ่านจากทรัพยากร
const UserProfile = () => {
const data = userData.read();
return (
Name: {data.name}
Age: {data.age}
);
};
const App = () => {
return (
Loading user data...}>
);
};
ในตัวอย่างนี้:
- ส่วนประกอบ `ErrorBoundary` ครอบส่วนประกอบ `Suspense`
- ส่วนประกอบ `Suspense` ครอบส่วนประกอบ `UserProfile`
- หากฟังก์ชัน `fetchData` ปฏิเสธด้วยข้อผิดพลาด ส่วนประกอบ `Suspense` จะตรวจจับการปฏิเสธ Promise และ `ErrorBoundary` จะตรวจจับข้อผิดพลาดที่เกิดจาก Suspense
- จากนั้น `ErrorBoundary` จะแสดง UI สำรอง
- หากข้อมูลดึงข้อมูลสำเร็จ ส่วนประกอบ `Suspense` จะแสดงส่วนประกอบ `UserProfile`
เทคนิคขั้นสูงและแนวทางปฏิบัติที่ดีที่สุด
การเพิ่มประสิทธิภาพประสิทธิภาพของ Suspense
- ใช้ Memoization: Memoize ส่วนประกอบที่แสดงผลภายใน Suspense Boundaries เพื่อป้องกันการแสดงผลซ้ำที่ไม่จำเป็น
- หลีกเลี่ยง Deep Suspense Trees: รักษาระดับความลึกของ Suspense Tree ให้ตื้นเพื่อลดผลกระทบต่อประสิทธิภาพการแสดงผล
- Prefetch Data: Prefetch ข้อมูลก่อนที่จะจำเป็นเพื่อลดโอกาสในการระงับ
Custom Error Boundaries
คุณสามารถสร้าง Custom Error Boundaries เพื่อจัดการข้อผิดพลาดบางประเภทหรือให้ข้อความแสดงข้อผิดพลาดที่ให้ข้อมูลมากขึ้น ตัวอย่างเช่น คุณสามารถสร้าง Error Boundary ที่แสดง UI สำรองที่แตกต่างกันโดยอิงตามประเภทของข้อผิดพลาดที่เกิดขึ้น
Server-Side Rendering (SSR) กับ Suspense
Suspense สามารถใช้กับ Server-Side Rendering (SSR) เพื่อปรับปรุงประสิทธิภาพการโหลดหน้าเว็บเริ่มต้นได้ เมื่อใช้ SSR คุณสามารถแสดงผลสถานะเริ่มต้นของแอปพลิเคชันของคุณล่วงหน้าบนเซิร์ฟเวอร์ จากนั้นสตรีมเนื้อหาที่เหลือไปยังไคลเอ็นต์ Suspense ช่วยให้คุณสามารถจัดการการดึงข้อมูลแบบอะซิงโครนัสระหว่าง SSR และแสดงตัวบ่งชี้การโหลดในขณะที่กำลังสตรีมข้อมูล
การจัดการสถานการณ์ข้อผิดพลาดที่แตกต่างกัน
พิจารณาสถานการณ์ข้อผิดพลาดที่แตกต่างกันเหล่านี้และวิธีจัดการกับสถานการณ์เหล่านั้น:
- Network Errors: จัดการ Network Errors อย่างสง่างามโดยแสดงข้อความแสดงข้อผิดพลาดที่ให้ข้อมูลแก่ผู้ใช้
- API Errors: จัดการ API Errors โดยแสดงข้อความแสดงข้อผิดพลาดที่เฉพาะเจาะจงกับข้อผิดพลาดที่เกิดขึ้น
- Unexpected Errors: จัดการ Unexpected Errors โดยบันทึกข้อผิดพลาดและแสดงข้อความแสดงข้อผิดพลาดทั่วไปแก่ผู้ใช้
Global Error Handling
ใช้กลไก Global Error Handling เพื่อตรวจจับข้อผิดพลาดที่ไม่ได้ตรวจจับโดย Error Boundaries สามารถทำได้โดยใช้ Global Error Handler หรือโดยการครอบแอปพลิเคชันทั้งหมดใน Error Boundary
ตัวอย่างและการใช้งานจริง
แอปพลิเคชัน E-commerce
ในแอปพลิเคชัน E-commerce สามารถใช้ Suspense เพื่อแสดงตัวบ่งชี้การโหลดขณะดึงข้อมูลผลิตภัณฑ์ และ Error Boundaries สามารถใช้เพื่อจัดการข้อผิดพลาดที่เกิดขึ้นระหว่างขั้นตอนการชำระเงิน ตัวอย่างเช่น ลองจินตนาการว่าผู้ใช้จากญี่ปุ่นกำลังเรียกดูร้านค้าออนไลน์ที่ตั้งอยู่ในสหรัฐอเมริกา รูปภาพและคำอธิบายผลิตภัณฑ์อาจใช้เวลาในการโหลด Suspense สามารถแสดงภาพเคลื่อนไหวการโหลดอย่างง่ายในขณะที่ข้อมูลนี้ถูกดึงมาจากเซิร์ฟเวอร์ที่อาจอยู่ห่างออกไปครึ่งโลก หาก Payment Gateway ล้มเหลวเนื่องจากปัญหาเครือข่ายชั่วคราว (พบได้ทั่วไปในโครงสร้างพื้นฐานอินเทอร์เน็ตที่แตกต่างกันทั่วโลก) Error Boundary สามารถแสดงข้อความที่ใช้งานง่ายซึ่งแจ้งให้ลองอีกครั้งในภายหลัง
แพลตฟอร์ม Social Media
ในแพลตฟอร์ม Social Media สามารถใช้ Suspense เพื่อแสดงตัวบ่งชี้การโหลดขณะดึงโปรไฟล์ผู้ใช้และโพสต์ และ Error Boundaries สามารถใช้เพื่อจัดการข้อผิดพลาดที่เกิดขึ้นเมื่อโหลดรูปภาพหรือวิดีโอ ผู้ใช้ที่เรียกดูจากอินเดียอาจพบว่าเวลาในการโหลดสื่อที่โฮสต์บนเซิร์ฟเวอร์ในยุโรปล่าช้า Suspense สามารถแสดงตัวยึดตำแหน่งจนกว่าเนื้อหาจะโหลดจนเต็ม หากข้อมูลโปรไฟล์ของผู้ใช้รายใดรายหนึ่งเสียหาย (หายากแต่เป็นไปได้) Error Boundary สามารถป้องกันไม่ให้ฟีด Social Media ทั้งหมดหยุดทำงาน โดยแสดงข้อความแสดงข้อผิดพลาดอย่างง่าย เช่น "ไม่สามารถโหลดโปรไฟล์ผู้ใช้" แทน
แอปพลิเคชัน Dashboard
ในแอปพลิเคชัน Dashboard สามารถใช้ Suspense เพื่อแสดงตัวบ่งชี้การโหลดขณะดึงข้อมูลจากหลายแหล่ง และ Error Boundaries สามารถใช้เพื่อจัดการข้อผิดพลาดที่เกิดขึ้นเมื่อโหลดแผนภูมิหรือกราฟ นักวิเคราะห์ทางการเงินในลอนดอนที่เข้าถึง Dashboard การลงทุนระดับโลกอาจกำลังโหลดข้อมูลจากตลาดหลักทรัพย์หลายแห่งทั่วโลก Suspense สามารถให้ตัวบ่งชี้การโหลดสำหรับแต่ละแหล่งข้อมูล หาก API ของตลาดหลักทรัพย์แห่งใดแห่งหนึ่งหยุดทำงาน Error Boundary สามารถแสดงข้อความแสดงข้อผิดพลาดเฉพาะสำหรับข้อมูลของตลาดหลักทรัพย์นั้น ป้องกันไม่ให้ Dashboard ทั้งหมดใช้งานไม่ได้
บทสรุป
React Suspense และ Error Boundaries เป็นเครื่องมือที่จำเป็นสำหรับการสร้างแอปพลิเคชัน React ที่ยืดหยุ่นและใช้งานง่าย การใช้ Suspense เพื่อจัดการสถานะการโหลด และ Error Boundaries เพื่อจัดการข้อผิดพลาดที่ไม่คาดคิด คุณสามารถปรับปรุงประสบการณ์ผู้ใช้โดยรวมและลดความซับซ้อนของกระบวนการพัฒนา คู่มือนี้ให้ภาพรวมที่ครอบคลุมของ Suspense และ Error Boundaries ครอบคลุมทุกอย่างตั้งแต่แนวคิดพื้นฐานไปจนถึงเทคนิคขั้นสูง การปฏิบัติตามแนวทางปฏิบัติที่ดีที่สุดที่ระบุไว้ในบทความนี้ คุณสามารถสร้างแอปพลิเคชัน React ที่แข็งแกร่งและเชื่อถือได้ ซึ่งสามารถจัดการได้แม้ในสถานการณ์ที่ท้าทายที่สุด
ในขณะที่ React ยังคงพัฒนาต่อไป Suspense และ Error Boundaries มีแนวโน้มที่จะมีบทบาทสำคัญมากขึ้นในการสร้างเว็บแอปพลิเคชันสมัยใหม่ การเชี่ยวชาญคุณสมบัติเหล่านี้ คุณสามารถนำหน้าและมอบประสบการณ์ผู้ใช้ที่ยอดเยี่ยมได้