淺談 React Hooks(一)

隨着不久前 React@16.8.0 的發佈,Hooks 也算是正式來到了幕前。我的以爲對React來講,Hooks 能夠算是一個里程碑式的功能。本文不會詳細介紹 Hooks,若是對 Hooks 還不是很瞭解的,能夠先看下 Introducing Hooksjavascript

Hooks 帶來了什麼

簡單來講 Hooks 帶來了能夠在 Function Components 使用 state 和其它 React 特性的能力。而這帶來的第一個很直觀的好處就是原來寫的 Function Components 由於需求變更須要增長 state 時,不再須要重構成 Class Components 了(重構再也不是火葬場了)。html

我的認爲 Hooks 帶來的最大益處就是可以幫咱們更好地組織業務代碼,提升代碼複用率。咱們經過一個例子來講明,假設有這麼一個需求:「組件須要根據瀏覽器寬度的變化,來顯示不一樣的內容」。java

咱們先用 Class Component 來實現:react

export default class ResizeClassComponent extends React.Component {
  constructor(props) {
    super(props);

    this.resizeHandler = null;
    this.state = {
      width: window.innerWidth,
    }
  }

  componentDidMount() {
    this.resizeHandler = () => {
      this.setState({
        width: window.innerWidth
      })
    }
    window.addEventListener('resize', this.resizeHandler);
  }

  componentWillUnmount() {
    window.removeEventListener('resize', this.resizeHandler);
  }

  render() {
    const { width } = this.state;
    return (
      <div>width: {width}</div>
    )
  }
}
複製代碼

目前來看沒什麼問題,可是若是說如今又有一個組件須要實現這個功能,同樣的代碼再寫一遍?那若是有不少組件都須要這個功能呢?每次都寫一遍確定不現實,有人會說用render props或者高階組件來處理這個問題,那就讓咱們來實現一下:git

// render props
class ResizeRenderProps extends React.Component {
  constructor(props) {
    super(props);

    this.resizeHandler = null;
    this.state = {
      width: window.innerWidth,
    }
  }

  componentDidMount() {
    this.resizeHandler = () => {
      this.setState({
        width: window.innerWidth
      })
    }
    window.addEventListener('resize', this.resizeHandler);
  }

  componentWillUnmount() {
    window.removeEventListener('resize', this.resizeHandler);
  }

  render() {
    return this.props.children(this.state.width);
  }
}

export default class ResizeClassComponent extends React.Component {
  render() {
    return (
      <ResizeRenderProps> {width => <div>width: {width}</div>} </ResizeRenderProps>
    )
  }
}
複製代碼
// 高階組件
function withResize(WrappedComponent) {
  return class ResizeHoc extends React.Component {
    constructor(props) {
      super(props);

      this.resizeHandler = null;
      this.state = {
        width: window.innerWidth,
      }
    }

    componentDidMount() {
      this.resizeHandler = () => {
        this.setState({
          width: window.innerWidth
        })
      }
      window.addEventListener('resize', this.resizeHandler);
    }

    componentWillUnmount() {
      window.removeEventListener('resize', this.resizeHandler);
    }

    render() {
      return <WrappedComponent width={this.state.width} />; } } } export default withResize(class ResizeClassComponent extends React.Component { render() { return ( <div>width: {this.props.width}</div> ) } }) 複製代碼

雖然實現了功能,可是兩種方式都不可避免地對原來組件作了重構,而且增長了一個層級,若是用的多了就會致使「wrapper hell」,拋開這個不談,render props高階組件 自己自帶的複雜度就不夠友好。github

那麼 Hooks 是怎麼解決的呢?瀏覽器

import React, { useState, useEffect } from 'react';

function useWindowWidth() {
  const [width, setWidth] = useState(window.innerWidth);

  useEffect(() => {
    const resizeHandler = () => setWidth(window.innerWidth);
    window.addEventListener('resize', resizeHandler);
    return () => window.removeEventListener('resize', resizeHandler)
  })

  return width;
}

export default function ResizeHooks() {
  const width = useWindowWidth();
  return (
    <div>width: {width}</div>
  )
}
複製代碼

是否是感受簡單又清楚?只須要自定義一個 Hook(其實也就是一個普通的函數啦,只不過用了內置的幾個Hook),使用的時候就像調用一個普通的函數同樣,沒有複雜的概念須要理解。正如前面所說,Hooks 能夠幫助咱們組織代碼,讓相關性的代碼都在一塊,而不是像在 Class Components 裏散落在各個生命週期函數中,貼個圖方便理解:app

圖片來源:twitter.com/prchdk/stat…函數

從圖中能夠發現邏輯相關的代碼都被單獨抽成了一個個 Hook,這意味着這部分有狀態的邏輯(stateful logic)能夠被複用,並且更容易理解。測試

稍微解釋下什麼叫「有狀態的邏輯(stateful logic)」,這裏的狀態指的就是 React 的 state,對應的無狀態的邏輯就是普通的函數啦。在 Hooks 以前,若是要複用這種有狀態的邏輯,除了上述的 render props高階組件以外就沒有別的更簡單直接的辦法了。而有了 Hooks 以後,這部分邏輯可以被單獨抽離出,職責更明確,從而使複用更加簡單,代碼更加清晰,並且也更便於測試。

嘗試一下

不知道我說的這些有沒有引發你對 Hooks 的興趣呢?其實從 React 官方的態度能夠看出是比較傾向於 Hooks 的,或者說是 Function Components,雖說是不會移除掉 Class Components(要是移除了,估計就炸了吧),可是能夠在項目中先小範圍試用下嘛,相信我你會喜歡上它的!

總結

前面寫的有點分散,最後再總結一下 Hooks 帶來的開發體驗上的提高:

  • 想給 Function Components 增長 state 時,無需重構代碼
  • 相比於render props高階組件,提供了更簡單直觀複用有狀態的邏輯(stateful logic)的方法
  • 代碼邏輯更加統一,更容易組織代碼結構
  • 便於測試

有了 Hooks 以後,Function Components 再也不是「高級字符串模版」啦!😝

以上只是我我的對 React Hooks 的一些想法,若有不對之處,歡迎指正~~

原文連接:github.com/sliwey/blog…

擴展閱讀:

相關文章
相關標籤/搜索