iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 3
0
自我挑戰組

玩轉 React 從0到1系列 第 22

【Day 22】React 關於 Hook (2)

  • 分享至 

  • xImage
  •  

關於 Hook 的方法與實作

useState

useState 是 hook 的函數,它接收的參數是狀態的初始值(initial state),它會返回一個 Array,第0位是當前的 State 的值,第1位是可以改變 State 的 function

檔案位置 src/Example.js:

import React, { useState } from 'react';
function Example() {
  const [ name, setName ] = useState('rainbow')   // 初始值
  const [ sex, setSex ] = useState('女')   // 初始值
  const [ age, setAge ] = useState(0)     // 初始值
  return (
    <div>
      <p>姓名:{name}</p>
      <p>性別:{sex}</p>
      <p>年紀:{age}(不可以點超過24下哈哈)</p>
      <button onClick={()=>{setAge(age+1)}}>增加年紀</button>
    </div>
  )
}
export default Example;

上方這個例子,我們會拆解為 宣告、讀取、修改這三方面來說明:
1.先使用 const [ parameter, setParameter ] = useState('ParameterValue')去宣告狀態。
這裡要注意這方法是 ES6 中的解構賦值,如果不寫成解構賦值要改寫成:

let _useState = useState(0)
let parameter = _useState[0]
let setParameter = _useState[1]

2.再來在 return 後運用 {paramter} 來讀取該 State 的值
3.最後使用{()=>{setParameter(parameterNewValue)}}搭配事件去修改 paramter 的值,關於 setParameter,它所接收的是將要更新的值,然後就交給 React 去進行重新渲染

useEffect

react 會等到 render 完後才去調用 useEffect,所以可以讓我們在函數元件中執行副作用的操作,可以把 useEffect 看作 ComponentDidMount、ComponentDidUpdate、ComponentWillUnMount的綜合體
這裏的副作用(Side Effect)指的是我們需要額外功能來取得或處理資料,像是 fetchData, eventHandling,之前有說一般都會在 ComponentDidMount 時處理

useEffect(callback, array)

  1. Callback: 回調函數,用於處理副作用邏輯

回調函數返回函數,相當於 ComponentWillUnmount

// 在回調函數返回一個函數,則是用於清理,像是 ComponentWillUnmount
useEffect(() => {
  // componentDidMount, componentDidUpdate 在這裡執行
  console.log('進入頁面')
  return () => {
    // componentWillUnmount 在這裡執行
    console.log('離開了')
  }
},[])

// 對應到 React Class Component用法:
componentDidMount() {
  console.log('進入頁面')
}
componentWillUnmount() {
  console.log('離開了')
}

回調函數裡進行副作用操作(像是請求資料),React 官方推薦在 componentDidMount 裡處理

// 在回調函數裡請求資料:
useEffect(() => {
  const fetchData = async() => {
    await fetch('data url').then(res => res.json())
  }
}, [])

// 對應到 React Class Component用法:
componentDidMount() {
  const fetchData = async() => {
    await fetch('data url').then(res => res.json())
  }
}
  1. Array: 用於控制與執行,分成不帶入、帶入[]、帶入[parameter]三種

如果沒有帶入 Array,則每一次更新後都會執行:

// 它在第一次渲染後每次更新都會執行:
useEffect(() => {
  console.log(`你已經點擊了 ${count} 次`)
})

// 對應到 React Class Component用法:
componentDidMount() {
  console.log(`你已經點擊了 ${count} 次`)
}
componentDidUpdate() {
  console.log(`你已經點擊了 ${count} 次`)
}

如果帶入[],則只在初次 render 後執行一次:

// 它只在第一次 render 後執行一次:
useEffect(() => {
  console.log(`你已經點擊了 ${count} 次`)
},[])

// 對應到 React Class Component用法:
componentDidMount() {
  console.log(`你已經點擊了 ${count} 次`)
}

如果帶入[parameter],則在 parameter 發生改變後執行:

// 它只在 state 數據發生改變後執行 Effect
useEffect(() => {
  console.log(`你已經點擊了 ${count} 次`)
}, [count]) // 只在 count 發生變化後執行

// 對應到 React Class Component用法:
componentDidUpdate(prevProps, prevState) {
  if (prevState.count !== this.state.count) {
    console.log(`你已經點擊了 ${count} 次`)
  }
}

開始實作

接下來搭配我們前幾天講的 react-router-dom 來實作看看計數器功能。
檔案位置 src/Example.js:

import React, { useState, useEffect } from 'react';
import { BrowserRouter , Route, Link } from 'react-router-dom';

function Index() {
  useEffect(() => {
    // componentDidMount, componentDidUpdate 在這裡執行
    console.log('useEffect=> Index頁面')
    return () => {
      // componentWillUnmount 在這裡執行
      console.log('離開Index頁面')
    }
  }, [])
  // 可以試著拿掉 []--------------(1)
  // 會發現每次 點擊增加按鈕 都會執行 'useEffect=> Index頁面' 與 '離開Index頁面' 
  return <h2>Rainbow Web</h2>
}

function SecondPage() {
  useEffect(() => {
    console.log('useEffect=> Second頁面')
    return () => {
      console.log('離開Second頁面')
    }
  }, [])   
  // 可以試著拿掉 []--------------(2)
  // 會發現每次 點擊增加按鈕 都會執行 'useEffect=> Second頁面' 與 '離開Second頁面'
  return <h2>Rainbow Sencond Page</h2>
}

function Example() {
  const [count, setCount] = useState(0)
  // 下方這個 useEffect 只在 count 發生變化時執行
  // 可以試著將 [count] 改成 [] --------------(3)
  // 會發現 useEffect 就只會在 render 完後執行一次
  useEffect(() => {
    console.log(`useEffect=> 已經點擊了${count}次數`)
    return () => {
      console.log('=========================')
    }
  },[count])
  return (
    <div>
      <p>你已經點擊了{ count } 次數</p>
      <button onClick={() => {setCount( count+1 )}}>增加</button>
      <BrowserRouter>
        <ul>
          <li><Link to="/">首頁</Link></li>
          <li><Link to="/secondPage/">第二分頁</Link></li>
        </ul>
        <Route path="/" exact component={Index} />
        <Route path="/secondPage/" component={SecondPage} />
      </BrowserRouter>
    </div>
  )
}
export default Example;

結論

  • 介紹了 Hook 的方法:useState, useEffect

/images/emoticon/emoticon18.gif 要開始燃燒了~衝刺


上一篇
【Day 21】React 關於 Hook
下一篇
【Day 23】React 關於 Hook(3)
系列文
玩轉 React 從0到130
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言