hooks 系列一:簡介

快來加入咱們吧!

"小和山的菜鳥們",爲前端開發者提供技術相關資訊以及系列基礎文章。爲更好的用戶體驗,請您移至咱們官網小和山的菜鳥們 ( xhs-rookies.com/ ) 進行學習,及時獲取最新文章。html

"Code tailor" ,若是您對咱們文章感興趣、或是想提一些建議,微信關注 「小和山的菜鳥們」 公衆號,與咱們取的聯繫,您也能夠在微信上觀看咱們的文章。每個建議或是贊同都是對咱們極大的鼓勵!前端

React-Hooks 簡介

react 爲何要有一個 hooks?

1.有狀態的類組件的複用太麻煩

react 的核心思想就是,將一個頁面拆成一堆獨立的,可複用的組件,而且用自上而下的單向數據流的形式將這些組件串聯起來。但若是你在大型的工做項目中用 react,你會發現你的項目中實際上不少 react 組件冗長且難以複用。特別是那些 class 的組件,它們自己包含了 state,很難進行復用。node

官方推薦解決方案react

  • 渲染屬性 - 使用一個值爲函數的 prop 來傳遞須要動態渲染的 nodes 或組件.以下面的代碼能夠看到咱們的Provider組件包含了全部跟狀態相關的代碼,而 MyComponent 組件則能夠是一個單純的展現型組件,這樣一來Provider就能夠單獨複用了
import MyComponent from 'components/myComponent'
class Provider extends React.Component {
  constructor(props) {
    super(props)
    this.state = { target: 'MyComponent' }
  }

  render() {
    return <div>{this.props.render(this.state)}</div>
  }
}

<Provider render={(data) => <MyComponent target={data.target} />} />
複製代碼

這個模式叫 Render-Props .web

固然通常狀況下,都會被寫成下面這樣的方式:ajax

<Provider>{(data) => <Cat target={data.target} />}</Provider>
複製代碼
  • HOC 高階組件 - 一個函數接受一個組件做爲參數,通過一系列加工後,最後返回一個新的組件.看下面的代碼示例,withUser 函數就是一個高階組件,它返回了一個新的組件,這個組件具備了它提供的獲取用戶信息的功能。
const withUser = (WrappedComponent) => {
  const user = localStorage.getItem('user')
  return (props) => <WrappedComponent user={user} {...props} />
}

const UserPage = (props) => (
  <div class="user-page"> <p>I'm the user, {props.user}!</p> </div>
)

export default withUser(UserPage)
複製代碼

以上這兩種模式看上去都挺不錯的,不少庫也運用了這樣的模式,就像咱們經常使用的 React-router 庫。可是這兩種模式,會增長代碼的層級關係。爲了表現的明顯,能夠安裝打開 React Devtools 看看代碼的組件嵌套,會發現嵌套次數太多太多。chrome

而若是咱們使用 hooks ,那就會簡潔不少,沒有多餘的層級嵌套。把各類想要的功能寫成一個一個可複用的自定義 hook,當你的組件想用什麼功能時,直接在組件裏調用這個 hook 便可。瀏覽器

2.生命週期函數裏面邏輯比較複雜

咱們一般但願一個函數只作一件事情,但咱們的生命週期鉤子函數裏一般同時作了不少事情。好比咱們須要在 componentDidMount 中發起請求獲取數據,綁定一些事件監聽等等。同時,有時候咱們還須要在 componentDidUpdate 作一遍一樣的事情。緩存

當咱們的這個頁面或者這個組件,變得複雜的時候,裏面的內容就會變多,邏輯的清晰度就會降低。微信

3.class 中的 this 指向問題

父組件給子組件傳遞函數時, 必須綁定 this

  • react 中的組件四種綁定 this 方法的區別
class App extends React.Component<any, any> {
  handleClick2

  constructor(props) {
    super(props)
    this.state = {
      num: 1,
      title: ' react study',
    }
    this.handleClick2 = this.handleClick1.bind(this)
  }

  handleClick1() {
    this.setState({
      num: this.state.num + 1,
    })
  }

  handleClick3 = () => {
    this.setState({
      num: this.state.num + 1,
    })
  }

  render() {
    return (
      <div> <h2>Ann, {this.state.num}</h2> <button onClick={this.handleClick2}>btn1</button> <button onClick={this.handleClick1.bind(this)}>btn2</button> <button onClick={() => this.handleClick1()}>btn3</button> <button onClick={this.handleClick3}>btn4</button> </div>
    )
  }
}
複製代碼
  • 構造函數中綁定 this,那麼每次父組件刷新的時候,若是傳遞給子組件其餘的 props 值不變,那麼子組件就不會刷新
  • render() 函數裏面綁定 this:由於 bind 函數會返回一個新的函數,因此每次父組件刷新時,都會從新生成一個函數,即便父組件傳遞給子組件其餘的 props 值不變,子組件每次都會刷新;
  • ()=>{} 箭頭函數:父組件刷新的時候,即便兩個箭頭函數的函數體是同樣的,都會生成一個新的箭頭函數,因此子組件每次都會刷新;
  • 使用類的靜態屬性:原理和第一種方法差很少,比第一種更簡潔

綜上所述,若是不注意的話,很容易寫成第三種寫法,致使性能上有所損耗

hooks 優勢

  • 能優化類組件存在問題

  • 能在無需修改組件結構的狀況下複用狀態邏輯(**自定義 Hooks **)

  • 能將組件中相互關聯的部分拆分紅更小的函數(好比設置訂閱或請求數據)

  • 反作用的關注點分離反作用指那些沒有發生在數據向視圖轉換過程當中的邏輯,如 ajax 請求、訪問原生dom 元素、本地持久化緩存、綁定/解綁事件、添加訂閱、設置定時器、記錄日誌等。以往這些反作用都是寫在類組件生命週期函數中的。而 useEffect 在所有渲染完畢後纔會執行,useLayoutEffect 會在瀏覽器 layout 以後,painting 以前執行。

小結

如今,咱們對 hooks 已經有了一個大概的瞭解。

那麼以後就開始咱們的基礎 hooks 教程了。

hooks 系列中,咱們主要介紹四個項目中經常使用的鉤子:useStateuseEffectuseRefsuseCallback.

若是大家想要了解一些其餘鉤子函數(useContextuseReduceruseMemouseImperativeMethodsuseMutationEffectuseLayoutEffect),能夠去官網查看

下節預告

在下節中,咱們將爲你們介紹 useState ,敬請期待!

相關文章
相關標籤/搜索