iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 21
0
自我挑戰組

React初心者30天的探索之路系列 第 21

[Day 21] React Hooks (上)-useState&useEffect

  • 分享至 

  • xImage
  •  

當functional component 遇上React Hooks,就好像白雪公主遇到她的王子…(我想不到更好的比喻了)有了Hooks,讓functional component也能擁有自己的state 、lifecycle,而且寫法也比原本的class component更加簡化

React Hooks的方法都以use開頭,也可以自己定義Hooks,至於為什麼要叫做Hooks? 需要用到的時候,透過鉤子Hooks將功能勾進來使用

useState

能夠讓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

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


上一篇
[Day 20] 用Redux Thunk 來處理非同步action
下一篇
[Day 22]React hook(中)-useContext&useReducer
系列文
React初心者30天的探索之路30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言