อัปเดตเมษายน 2020:
ดูเหมือนว่าปัญหาจะได้รับการแก้ไขแล้วใน React 16.13.1 ล่าสุดโปรดดูตัวอย่างแซนด์บ็อกซ์นี้ ขอบคุณ @abernier ที่ชี้ให้เห็นสิ่งนี้
ฉันได้ทำการวิจัยและพบความแตกต่างที่สำคัญอย่างหนึ่ง:
React ไม่ประมวลผลข้อผิดพลาดจากวิธีการ async lifecycle
ดังนั้นหากคุณเขียนสิ่งนี้:
componentDidMount()
{
throw new Error('I crashed!');
}
จากนั้นข้อผิดพลาดของคุณจะถูกจับโดยขอบเขตของข้อผิดพลาดและคุณสามารถประมวลผลและแสดงข้อความที่สวยงามได้
หากเราเปลี่ยนรหัสดังนี้:
async componentDidMount()
{
throw new Error('I crashed!');
}
ซึ่งเทียบเท่ากับสิ่งนี้:
componentDidMount()
{
return Promise.reject(new Error('I crashed!'));
}
จากนั้นข้อผิดพลาดของคุณจะถูกกลืนหายไปอย่างเงียบ ๆข้อผิดพลาดของคุณจะถูกกลืนกินอย่างเงียบอัปยศคุณตอบสนอง ...
ดังนั้นเราจะประมวลผลข้อผิดพลาดได้อย่างไร? วิธีเดียวที่ดูเหมือนจะชัดเจนเช่นนี้:
async componentDidMount()
{
try
{
await myAsyncFunction();
}
catch(error)
{
//...
}
}
หรือเช่นนี้:
componentDidMount()
{
myAsyncFunction()
.catch(()=>
{
//...
});
}
หากเรายังคงต้องการให้ข้อผิดพลาดของเราไปถึงขอบเขตข้อผิดพลาดฉันสามารถคิดถึงเคล็ดลับต่อไปนี้:
- ตรวจจับข้อผิดพลาดทำให้ตัวจัดการข้อผิดพลาดเปลี่ยนสถานะส่วนประกอบ
- หากสถานะระบุข้อผิดพลาดให้โยนออกจาก
render
เมธอด
ตัวอย่าง:
class BuggyComponent extends React.Component {
constructor(props) {
super(props);
this.state = { error: null };
}
buggyAsyncfunction(){ return Promise.reject(new Error('I crashed async!'));}
async componentDidMount() {
try
{
await this.buggyAsyncfunction();
}
catch(error)
{
this.setState({error: error});
}
}
render() {
if(this.state.error)
throw this.state.error;
return <h1>I am OK</h1>;
}
}