當functional component 遇上React Hooks,就好像白雪公主遇到她的王子…(我想不到更好的比喻了)有了Hooks,讓functional component也能擁有自己的state 、lifecycle,而且寫法也比原本的class component更加簡化
React Hooks的方法都以use開頭,也可以自己定義Hooks,至於為什麼要叫做Hooks? 需要用到的時候,透過鉤子Hooks將功能勾進來使用
能夠讓functional component建立自己的state,useState裡面傳入的是state的初始值,然後會回傳一個陣列,透過解構拿到state的當前值以及更新state的setState方法,可以在functional component建立多個useState!跟之前class component setState比起來,個人比較喜歡這種寫法,每次更新值都是針對當前的值,而不是一個對state物件裡的屬性操作,較為單純。
useState也可以傳入函式,但必須回傳值
const [count, setCount] = useState(()=> return 0})
點擊按鈕數字就會自動加1
import React, {useState, Fragment, useEffect} from 'react';
function HooksExample() {
const [count, setCount] = useState(0);
return (
<Fragment>
<h1>count {count}</h1>
<button onClick={() => { setCount(count+1)}}>click</button>
</Fragment>
)
}
export default HooksExample
此時發生一點小插曲,存檔之後,想看一下畫面發現報錯了!
反覆看了程式碼真的一頭霧水,只好求救google大神,才發現我的React不小心包在大括號裡面, 因為React預設為export default,所以一定要放在大括號外面,明明已經寫過很多遍,但是恍神的時候還是有可能寫錯,而且一時半刻找不出問題在哪裡orz
import React, {useState, Fragment} from 'react';
useEffect用來處理副作用(side effect) ,什麼是副作用?就要先了解pure function
什麼是pure function?
一個funciton輸入相同的參數,會輸出相同的結果,以React來說就是給予相同的props,會渲染出相同的畫面
什麼是副作用(Side Effect)?
任何與function回傳值沒有相關的操作,像是ajax請求、監聽事件、手動修改DOM等等,可能會造成預期之外的影響
透過監聽state、 props的變化,來決定要不要更新 ,可以說是生命週期componentDidMount、componentDidUpdate、componentWillUnmount的集合版,會接受兩個參數,第一個參數是非同步的操作的函式,有點像是callback function的概念,在component進到哪個週期需要執行的動作
第二個參數為一個陣列,是給useEffect判斷要不要執行函式的變數,如果這個參數有更動才會執行function,第二個參數如果放一個空陣列,等同於是componentDidMount,如果放的不是空陣列,初始渲染會執行一次,陣列裡面的資料有異動會在執行一次(componentDidUpdate)。
userEffect(()=>{
//初始渲染執行一次,資料有變化再更新一次等於componentDidUpdate
},[data])
下面的例子是在componentDidMount階段呼叫api取得資料,然後再渲染到頁面上
import React, {useState, Fragment, useEffect} from 'react';
function HooksExample() {
const [count, setCount] = useState(0);
const [list, setList] = useState([]);
useEffect(()=>{
fetch('https://api.kcg.gov.tw/api/service/Get/b4dd9c40-9027-4125-8666-06bef1756092')
.then(response=>response.json())
.then((data)=>{
setList(data.data.retVal)
setList(data.data.retVal)
console.log('data',data)
})
},[])
return (
<Fragment>
<h1>count {count}</h1>
<button onClick={() => { setCount(count+1)}}>click</button>
<ul>
{list.map((item)=>{
return (<li>
{item.sna}
</li>)
})}
</ul>
</Fragment>
)
}
export default HooksExample
假如第二個參數什麼都沒傳,就會變成每次渲染都會觸發,可能會發生無窮迴圈的問題!
useEffect也可以回傳一個clean up的函式來執行component銷毀前要做的事情,像是清除計時器、取消api請求等等,等同於componentWillUnmount
useEffect(() => {
const timer = setInterval(() => {
setCount(count=>count+1)
}, 1000);
return () =>{
clearInterval(timer)
}
}, [])
可以同時使用多個useEffect沒問題,明天會繼續介紹useContext、useRedux