首先咱們要明白的是React 16.8 的新增特性。它可讓咱們在不編寫 class 的狀況下使用 state 以及其餘的 React 特性。那麼就會有一個問題,當咱們處理業務需求的時候,還須要用class嗎?在這裏告訴你們,仍是須要的,由於Hook目前還不能徹底知足咱們的業務需求,這點,下文會講到,那麼讓咱們來看一下勁爆的React Hook吧!(React 16.8.0 是第一個支持 Hook 的版本。升級時,請注意更新全部的 package,包括 React DOM。React Native 將在下一個穩定版本中支持 Hook。)react
第一個Hook:ajax
import React, { useState } from 'react'; function Example() { // 聲明一個新的叫作 「count」 的 state 變量 const [count, setCount] = useState(0); return ( <div> <p>You clicked {count} times</p> <button onClick={() => setCount(count + 1)}> Click me </button> </div> ); }
在這裏,說一下,useState 即是一個Hook,你是否是很好奇,一個計時器不一樣於咱們以往的寫法。編程
在這裏,useState 就是一個 Hook 。經過在函數組件裏調用它來給組件添加一些內部 state。React 會在重複渲染時保留這個 state。useState 會返回一對值:當前狀態和一個讓你更新它的函數,你能夠在事件處理函數中或其餘一些地方調用這個函數。它相似 class 組件的 this.setState,可是它不會把新的 state 和舊的 state 進行合併。數組
useState 惟一的參數就是初始 state。在上面的例子中,咱們的計數器是從零開始的,因此初始 state 就是 0。值得注意的是,不一樣於 this.state,這裏的 state 不必定要是一個對象 —— 若是你有須要,它也能夠是。這個初始 state 參數只有在第一次渲染的會被用到。瀏覽器
在上一章節咱們提到過一個簡單的計數器,那麼究竟什麼是Hook呢?Hook 是一些可讓你在函數組件裏「鉤入」 React state 及生命週期等特性的函數。那麼說白了,Hook並非什麼神奇的」人物「,只是一個咱們天天都在接觸實用的函數。dom
function ExampleWithManyStates() { // 聲明多個 state 變量! const [age, setAge] = useState(42); const [fruit, setFruit] = useState('banana'); const [todos, setTodos] = useState([{ text: 'Learn Hooks' }]); // ... }
如上所提到的useState 即是咱們在處理數據時的操做,那麼有沒有什麼好的辦法可讓我對行爲進行方便的處理呢。顯然是有的。當咱們作一些行爲的時候必然會有一些反作用的產生,這裏的反作用並非咱們生活中所提到的給一件事情帶來很差的影響,或者很差的效果。那麼究竟什麼是反作用呢?ide
那麼,當咱們理解了反作用後,那麼咱們的useEffect 就是一個 Effect Hook,給函數組件增長了操做反作用的能力。它跟 class 組件中的 componentDidMount、componentDidUpdate 和 componentWillUnmount 具備相同的用途,只不過被合併成了一個 API。函數
import React, { useState, useEffect } from 'react'; function Example() { const [count, setCount] = useState(0); // 至關於 componentDidMount 和 componentDidUpdate: useEffect(() => { // 使用瀏覽器的 API 更新頁面標題 document.title = `You clicked ${count} times`; }); return ( <div> <p>You clicked {count} times</p> <button onClick={() => setCount(count + 1)}> Click me </button> </div> ); }
當你調用 useEffect 時,就是在告訴 React 在完成對 DOM 的更改後運行你的「反作用」函數。因爲反作用函數是在組件內聲明的,因此它們能夠訪問到組件的 props 和 state。默認狀況下,React 會在每次渲染後調用反作用函數 —— 包括第一次渲染的時候。性能
咱們能在全部的地"肆無忌憚"的使用如此之方便的Hook嗎,答案是暫時不能夠的,由於
自定義 Hook 更像是一種約定而不是功能。若是函數的名字以 「use」 開頭並調用其餘 Hook,咱們就說這是一個自定義 Hook。 useSomething 的命名約定可讓咱們的 linter 插件在使用 Hook 的代碼中找到 bug。
你能夠建立涵蓋各類場景的自定義 Hook,如表單處理、動畫、訂閱聲明、計時器,甚至可能還有更多咱們沒想到的場景。咱們很期待看到 React 社區會出現什麼樣的自定義 Hook。
首先讓Demo
1: import React, { useState } from 'react'; //引入 React 中的 useState Hook。它讓咱們在函數組件中存儲內部 state。 2: 3: function Example() { 4: const [count, setCount] = useState(0); //在 Example 組件內部,咱們經過調用 useState Hook 聲明瞭一個新的 state 變量。它返回一對值給到咱們命名的變量上。咱們把變量命名爲 count,由於它存儲的是點擊次數。咱們經過傳 0 做爲 useState 惟一的參數來將其初始化爲 0。第二個返回的值自己就是一個函數。它讓咱們能夠更新 count 的值,因此咱們叫它 setCount 5: 6: return ( 7: <div> 8: <p>You clicked {count} times</p> 9: <button onClick={() => setCount(count + 1)}> //當用戶點擊按鈕後,咱們傳遞一個新的值給 setCount。React 會從新渲染 Example 組件,並把最新的 count 傳給它。 10: Click me 11: </button> 12: </div> 13: ); 14: }
import React, { useState, useEffect } from 'react'; function Example() { const [count, setCount] = useState(0); useEffect(() => { document.title = `You clicked ${count} times`; }); return ( <div> <p>You clicked {count} times</p> <button onClick={() => setCount(count + 1)}> Click me </button> </div> ); }
經過使用這個 Hook,你能夠告訴 React 組件須要在渲染後執行某些操做。React 會保存你傳遞的函數(咱們將它稱之爲 「effect」),而且在執行 DOM 更新以後調用它。在這個 effect 中,咱們設置了 document 的 title 屬性,不過咱們也能夠執行數據獲取或調用其餘命令式的 API。
將 useEffect 放在組件內部讓咱們能夠在 effect 中直接訪問 count state 變量(或其餘 props)。咱們不須要特殊的 API 來讀取它 —— 它已經保存函數做用域中。Hook 使用了 JavaScript 的閉包機制,而不用在 JavaScript 已經提供瞭解決方案的狀況下,還引入特定的 React API。
是的,默認狀況下,它在第一次渲染以後和每次更新以後都會執行。(咱們稍後會談到如何控制它。)你可能會更容易接受 effect 發生在「渲染以後」這種概念,不用再去考慮「掛載」仍是「更新」。React 保證了每次運行 effect 的時,DOM 都已經更新完畢。