Lala Code

Lala 的前端大補帖,歡迎一起鑽研前端技術😊

0%

React生命週期、錯誤處理

React

在不同階段的生命週期,如掛載時、更新時、卸載時,分別會對應不同的函式

圖片截圖自: 網站版 React Life Cycle 網友製

常用的生命週期有: constructor、render、componentDidMount、componentDidUpdate、componentWillUnmount

constructor 建構函式

組件生成後第一個執行,唯一可以指定 state 的地方

constructor 注意
❌ 不可呼叫 setState
❌ 不可呼叫 ajax
❌ 不要將 props 指定為 state

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Counter extends Component {
constructor(props) {
super(props); // super 為 Counter 的父類別 Component
this.state = { count: 0 };
this.handClick = this.handClick.bind(this);
}
handClick() {
// do something
}
render() {
return (
<div></div>
);
}
}



render 渲染函式

把資料轉成視覺畫面,可以讀取 props、state,並且會 return 資料

return 可以是一個 jsx 元素、Array、number、boolean、string、null、portal

在 React 16 以後,元素可以是不需被一個標籤包住

你可以用 return Array

1
2
3
4
5
6
render() {
return [
<h1>title</h1>,
<div>123</div>
];
}

或是用虛擬的包裝元素 Fragment 包住,渲染出來後 Fragment 不會顯示在 HTML上

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import React, { Component, Fragment } from 'react';

class Counter extends Component {
render() {
return(
<Fragment>
<h1>title</h1>
<div>123</div>
</Fragment>
)
}
}

export default Counter;

或是直接給空標籤,需要設定 babel,效果也會跟 Fragment 一樣

1
2
3
4
5
6
7
8
render() {
return(
<>
<h1>title</h1>
<div>123</div>
</>
)
}

render 注意
❌ 不可呼叫 setState,setState 會更新 state,state 改變後重新 render,會無窮迴圈
❌ 不可呼叫 ajax


componentDidMount 組件初次 render 完成

組件第一次 render 完後執行,

可使用 dom、讀取 ajax 資料

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class Counter extends Component {
state = {
items: []
}
componentDidMount() {
this.fetchList();
}
fetchList = async () => {
const res = await fetch('https://.../api');
const data = await res.json();
this.setState({
items: data,
})
}
render() {
const { items } = this.state;
return(
<ul>
{items.map((item) => (
<li key={item.id}>{item.text}</li>
))}
</ul>
)
}
}



componentDidUpdate 狀態屬性更新

1
componentDidUpdate(prevProps, PrevState, snapshot)

只要 state 或 props 有變動,就會執行 componentDidUpdate

componentDidUpdate 需要做一個 state 或 props 變動的條件判斷

1
2
3
4
5
6
7
8
componentDidUpdate(prevProps, PrevState, snapshot) {
if(prevProps.userID !== this.props.userID) {
this.fetchUser(this.props.userID);
this.setState({
// do something
})
}
}

snapshot 是指 getSnapshotBeforeUpdate 回傳的值,可判斷 snapshot 的值,執行動作


componentWillUnmount 卸載前

組件將要銷毀前執行

常用於移除偵聽 removeEventListener、clearTimeout、clearInterval

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
componentDidMount() {
window.addEventListener('scroll', this.onScroll);
}
componentDidUpdate(prevProps, prevState) {
this.timeoutTimer = setTimeout(() => { }, 3000);
this.intervalTimer = setInterval(() => { }, 3000);
}
componentWillUnmount() {
window.removeEventListener('scroll', this.onScroll);
clearTimeout(this.timeoutTimer);
clearInterval(this.intervalTimer);
}
onScroll = () => {
// do someting
}

不常用的生命週期: getDerivedStateFromProps、shouldComponentUpdate、getSnapshotBeforeUpdate

getDerivedStateFromProps

1
2
3
static getDerivedStateFromProps(nextProps, prevState) {
return {}
}

每次 mounted、props、state 的變動都會執行,並 return 新的 state,如不須變更須回傳 nu

靜態函式,不會有 this、不能做非同步操作


shouldComponentUpdate

1
2
3
shouldComponentUpdate(nextProps, nextState) {
return true
}

控制組件要不要更新,return boolean,預設為 true


getSnapshotBeforeUpdate

1
2
3
getSnapshotBeforeUpdate(prevProps, prevState) {
return
}

組件實際變更之前執行

可以記錄 dom 變更之前的狀態,return 無限制型態


錯誤處理

抓組件在生命週期發生的錯誤,不會抓到 Promise 回傳的錯誤

getDerivedStateFromError

1
static getDerivedStateFromError(error)

如果組件發生錯誤,想改變視覺狀態,可在 getDerivedStateFromError 執行錯誤處理



componentDidCatch(error, info)

1
componentDidCatch(error, info)

如果組件發生錯誤,想回傳錯誤訊息給後端或導頁,可在 componentDidCatch 執行



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import React, { Component } from 'react';
import Child from "./Child";

class Counter extends Component {
state = {
hasError: false
}

static getDerivedStateFromError(error) {
return { hasError: true }
}

componentDidCatch(error, info) {
axios.post('/api/logger', { info })
}

render() {
const { hasError } = this.state;
if(hasError) {
return <h1>Error</h1>
}
return(
<div>
<h1>Success</h1>
<Child />
</div>
)
}
}

export default Counter;


Hey!想學習更多前端知識嗎?

最近 Lala 開了前端課程 👉【實地掌握RWD - 12小時新手實戰班】👈
無論您是 0 基礎新手,又或是想學 RWD 的初學者,
我們將帶你從零開始,深入了解並掌握 RWD 響應式網頁設計的核心技術,快來一起看看吧 😊



🚀線上課程分享

線上課程可以加速學習的時間,省去了不少看文件的時間XD,以下是我推薦的一些課程
想學習更多關於前後端的線上課程,可以參考看看。

Hahow

Hahow 有各式各樣類型的課程,而且是無限次數觀看,對學生或上班族而言,不用擔心被時間綁住



六角學院

如果你是初學者,非常推薦六角學院哦!
剛開始轉職也是上了六角的課,非常的淺顯易懂,最重要的是,隨時還有線上的助教幫你解決問題!


Udemy

Udemy 裡的課程非常的多,品質普遍不錯,且價格都滿實惠的,CP值很高!
也是很多工程師推薦的線上課程網站。
❤️