嗨,我是Hogan
目前在經營自己的自媒體 hogan.tech
主要分享一些有關於程式碼、軟體和科技業經驗分享
有興趣的讀者可以進一步關注我,進而獲得更多資訊唷!
未來文章一併更新於此網站 Hogan.B Lab
並且包含多語系 繁體中文、英文、日文、簡體中文
觀看分類:React 白話文運動、其他系列
如果想要快速查找其他文章請點選目錄
成立 hogan.tech 的初衷是
希望每個正在這條路上探索的人,
都可以透過 Hogan.tech 嘗試進入程式領域。
前一篇介紹另一個 hook 函式
這一篇則是會繼續深入介紹useEffect
先來複習一下前一篇useEffect的實作
首先建立一個 checkBox 元件,先建立一個useState( ),除了給予初始值以外,也給了一個setting。
不過元件渲染後,還是希望針對已修改的狀態,更新元件以及資料,因此將
console.log(`checked: ${checked.toString()}`);
放入 useEffect( ) 函式之中,之後只要元件狀態有更新,就會重新渲染一次。
import React, { useState } from 'react'
import { useEffect } from 'react';
function CheckBox() {
const [checked, setChecked] = useState(false);
useEffect(() => {
console.log(`checked: ${checked.toString()}`);
})
return (
<>
<input
type="checkbox"
value={checked}
onChange={() => setChecked(checked => !checked)}
/>
{checked ? "checked" : "not checked"}
</>
)
}
這邊可以先來看一下這個元件,如果直接執行這個元件,
function Component() {
console.log("render components");
useEffect(() => {
console.log("useEffect trigger")
})
return (
<>
{console.log("render JSX")}
</>
)
}
如果呼叫上面的元件,會依照順序印出三行的結果
分別為
理由是因為載入元件後會先執行裡面的函式
Component元件第二行會先被執行,印出 render components
接下來遇到 useEffect 則會擺到渲染後去執行
然後再回傳 JSX 時,執行裡面的程式,印出 render JSX
最後回傳完畢後再去執行useEffect裡面的函式,印出 useEffect trigger
這樣的執行順序也與元件的生命週期有關
以上面的流程來說
那如果我們修改元件的狀態,元件因此重新渲染呢?
除了渲染元件的步驟以外,其實也會重新執行 useEffect 裡面的函式
import React from 'react'
import { useState } from 'react';
import { useEffect } from 'react';
export default function EffectComponent() {
console.log("render components");
const [value, setValue] = useState(0)
useEffect(() => {
console.log("useEffect trigger")
console.log(value)
}, [value])
return (
<>
<button onClick={() => setValue(value + 1)}></button>
{console.log("render JSX")}
</>
)
}
這邊另外搭配了 useState 給予元件一個狀態叫做value,點擊按鈕後可以讓 value 加一
如果實際執行程式,並且點擊按鈕後,會分別印出以下
不過這邊也要跟讀者強調一下,如果不熟悉 useEffect 的讀者,可能一不小心就會陷入無窮渲染
import React from 'react'
import { useState } from 'react';
import { useEffect } from 'react';
export default function EffectComponent() {
console.log("render components");
const [value, setValue] = useState(0)
useEffect(() => {
console.log(value)
setData()
})
const setData = () => {
setValue(value + 1)
}
return (
<>
<button onClick={setData}></button>
{console.log("render JSX")}
</>
)
}
如果直接執行以上的程式,會看到 console 一直跑,並且數字一直往上,為什麼呢?
理由是因為,以上面的流程來說
就會進入無窮渲染
那麼我們要怎麼避免上面的情境呢?
在useEffect 的語法中
useEffect(callback function,[dependencies])
後面會放入一個陣列,陣列裡面擺入的就是dependency
也可以選擇一個空的陣列,或是直接不加入陣列,都會有不同的效果
這一張圖我覺得概念相當清晰,這邊也附上 原文網址
也相當推薦讀者可以看此文章,更熟悉 useEffect 的概念,回到dependency 本身
在useEffect 函式中,如果dependency 沒有任何改變,就不執行useEffect內的函式
如果放上空的陣列,則只會執行一次
import React from 'react'
import { useState } from 'react';
import { useEffect } from 'react';
export default function EffectComponent() {
console.log("render components");
const [value, setValue] = useState(0)
useEffect(() => {
setData()
}, [])
const setData = () => {
console.log(value)
setValue(value + 1)
}
return (
<>
<button onClick={setData}></button>
{console.log("render JSX")}
</>
)
}
這邊也歡迎讀者自行試試看
以我個人來說,我覺得useEffect 既好用又複雜,因為他需要去判斷裡面的相依性
但是好處是使用useEffect就可以解決很多事情
如果有任何建議與疑問也歡迎留言!
如果喜歡此系列文章,請不吝於按下喜歡及分享,讓更多人看到唷~