iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 9
2
Modern Web

React + D3 的正確姿勢系列 第 9

Day09-React Hook

前言

今天要來介紹本系列文中第一個非常重要的觀念了,在前面的文章有提到元件的比較其中提到了 Functional Component ,其實 Functional Component 有個非常大的缺陷,在今天的文章就是要來談談 React 是如何利用新推出的 Hook 來改善 Functional Component 的缺陷。

Functional Component 缺陷

在正式進入主題之前還是先來談一下 Functional Component 的缺陷,假如我今天想實作一個計數器,由於計數器會是一個很小的元件,所以一開始在實作的時候一定會想說直接用 Functional Component 的方式實作,但這時候就會遇到一個問題,我要如何改變 state 讓我的計數器可以不斷的紀錄點擊幾次,為了改變 state 就只好把這個元件變成普通的 React.Component ,這解法看似很好但心裡一定很不是滋味,畢竟以前在寫閉包的時候計數器也只要短短的幾行程式碼就可以完成,為何到了 React 之後就要變的這麼大一包,其實不只工程師有這問題,開發者也有這問題,所以 React Hook 誕生了。

// 閉包寫法
function counter() {
  let counter = 1
  return function() {
    return counter++
  }
}

// react 元件寫法
class App extends Component {
  state = { counter: 0 }
  
  handleClick = () => this.setState(prevState => ({ counter: prevState.counter + 1 }))
  
  render() {
    return (
      <div>
        <button onClick={this.handleClick}>計數器</button>
        <p>您點擊了{this.state.counter}次</p>
      </div>
    )
  }
}

React Hook

其實 React Hook 就是更進階版的 Functional ComponentHook 的出現讓 Functional Component 可以操控 state 以及一些基本的 Component life cycle ,而 Hook 有非常多的 API ,有興趣的讀者可以參考這個連結,筆者這邊就列出幾個比較常用到的 API 來做解釋。

  • useState

    useState 本身是個 function ,會回傳初始化的 state 以及控制此 statehandler function ,用個簡單的範例碼來示範一下 useState 的用法:

    import React, { useState } from 'react'
    
    const [ count, setCount ] = useState(0)
    
    console.log(count)      // 0
    console.log(setCount)   // function() {...}
    

    useState 的參數代表著初始化 state 的值,上面的例子筆者寫了 useState(0) 就代表初始化的 state 會是 0 ,由於 useState 在帶了參數後會回傳一個陣列,因此筆者在這邊運用了 ES6 的解構賦值,讓 state 以及 handler function 可以快速地建立出來,有了這些觀念後就可以撰寫比較進階的 Functional Component 啦!

    import React, { useState } from 'react'
    
    const Counter = () => {
      const [ count, setCount ] = useState(0)
      return (
        <div>
          <button onClick={() => setCount(count + 1)}>計數器</button>
          <p>您點擊了{count}次</p>
        </div>
      )
    }
    

  • useEffect

    useEffect 本身也是個 function ,但 useEffect 的出現就是為了讓 Functional Component 可以模擬最基本的 Component life cycle 像是 componentDidMount 以及 componentDidUpdate ,所以 useEffect 內部寫的會是一個 callback function ,這邊也用個簡單的範例碼來示範一下寫法:

    import React, { useEffect } from 'react'
    
    useEffect(() => {
      // do something
    })
    

    有沒有覺得 useEffectuseState 更單純了呢XD

接下來讓我們將 useState 以及 useEffect 結合在一起吧!讓這個 Functional Component 看起來更像一般的 React.Component ,這邊一樣用個小例子帶大家演繹一下寫法:

import React, { useState, useEffect }

function getTime() {
  const time = new Date()
  const hour = time.getHours()
  const minute = time.getMinutes()
  const second = time.getSeconds()
  return `${hour}:${minute}:${second}`
}

const Timer = () => {
  const [ time, setTime ] = useState('')

  useEffect(() => {
    const DateTimeNow = getTime()
    const id = setInterval(() => setTime(DateTimeNow), 1000)
    return () => clearInterval(id)
  })

  return (
    <h4>{time}</h4>
  )
}

simple React Hook

總結

今天介紹了 React Hook 這個強大的功能,相信大家以後一定會更常利用 Functional Component 搭配 Hook 的方式來撰寫小元件,而筆者之後也是會一直利用 React Hook 來進行後續的實作,所以大家一定要看懂今天的文章。

如果有問題歡迎在下面留言給我,沒問題的話明天要來教大家如何在本地端架設 React 的開發環境了。


上一篇
Day08-List and keys
下一篇
Day10-React環境架設(create-react-app)
系列文
React + D3 的正確姿勢30

尚未有邦友留言

立即登入留言