React Hooks 是 React 16.8 的新增特性。它可讓你在不編寫 class 的狀況下使用 state 以及其餘的 React 特性。react
前言
本篇主要以講幾個經常使用的api爲主。api
1.useState
這個例子用來顯示一個計數器。當你點擊按鈕,計數器的值就會增長,如今咱們的寫法以下,數組
class Example extends React.Component { constructor(props) { super(props); this.state = { count: 0 }; } render() { return ( <div> <p>You clicked {this.state.count} times</p> <button onClick={() => this.setState({ count: this.state.count + 1 })}> Click me </button> </div> ); } }
這是咱們所熟悉的寫法,替換成useState後ide
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> ); }
- 1.首先經過在函數組件裏調用useState()來給組件添加一些內部 state,(React 會在重複渲染時保留這個 state)。
- 2.useState()能夠傳入一個參數,傳入的參數就是初始的state,在上面例子當中,0就是初始值。【這個初始 state 參數只有在第一次渲染的會被用到。】
- 3.useState() 會返回一對值:當前狀態和一個讓你更新它的函數(你能夠在事件處理函數中或其餘一些地方調用這個函數,它相似 class 組件的 this.setState,可是它不會把新的 state 和舊的 state 進行合併。)
- 4.能夠經過useState聲明多個state變量,以下
function ExampleWithManyStates() { // 聲明多個 state 變量! const [age, setAge] = useState(42); const [fruit, setFruit] = useState('banana'); const [todos, setTodos] = useState([{ text: 'Learn Hooks' }]); // ... }
2.useEffect
useEffect 就是一個 Effect Hook,給函數組件增長了操做反作用的能力。它跟 class 組件中的 componentDidMount、componentDidUpdate 和 componentWillUnmount 具備相同的用途,只不過被合併成了一個 API。函數
依然是先上例子ui
class Example extends React.Component { constructor(props) { super(props); this.state = { count: 0 }; } componentDidMount() { document.title = `You clicked ${this.state.count} times`; } componentDidUpdate() { document.title = `You clicked ${this.state.count} times`; } render() { return ( <div> <p>You clicked {this.state.count} times</p> <button onClick={() => this.setState({ count: this.state.count + 1 })}> Click me </button> </div> ); } }
import React, { useState, useEffect } from 'react'; function Example() { const [count, setCount] = useState(0); // 至關於 componentDidMount 和 componentDidUpdate: useEffect(() => { document.title = `You clicked ${this.state.count} times`; }); return ( <div> <p>You clicked {count} times</p> <button onClick={() => setCount(count + 1)}> Click me </button> </div> ); }
-
1.默認狀況下,React 會在每次渲染後調用反作用函數 —— 包括第一次渲染的時候。this
-
2.反作用函數還能夠經過返回一個函數來指定如何「清除」反作用。它的執行順序是,每次頁面更新前,先執行return的函數,而後在執行useEffect裏面的內容。spa
import React, { useState, useEffect } from 'react'; function Example() { const [count, setCount] = useState(0); useEffect(() => { console.log(`You clicked ${count} times`); return () => { console.log('每次頁面更新前,我會先被執行'); } }); return ( <div> <p>You clicked {count} times</p> <button onClick={() => setCount(count + 1)}> Click me </button> </div> ); }
- 3.跟 useState 同樣,你能夠在組件中屢次使用 useEffect,所以經過使用 Hook,你能夠把組件內相關的反作用組織在一塊兒(例如建立訂閱及取消訂閱),而不要把它們拆分到不一樣的生命週期函數裏。
- 4.useEffect還能夠傳入第二個參數,指定當某個值發生變化的時候,才觸發反作用.
useEffect(() => { document.title = `You clicked ${count} times`; }, [count]); // 僅在 count 更改時更新
- 5.若是想執行只運行一次的 effect(僅在組件掛載和卸載時執行),能夠傳遞一個空數組([])做爲第二個參數。
3.useReducer
useState 的替代方案。它接收一個形如 (state, action) => newState 的 reducer,並返回當前的 state 以及與其配套的 dispatch 方法。(若是你熟悉 Redux 的話,就已經知道它如何工做了。)code
// reducer.js export const initialState = {count: 0}; export default (state, action) => { switch (action.type) { case 'increment': return {count: state.count + 1}; case 'decrement': return {count: state.count - 1}; default: throw new Error(); } } // Counter.js import React, { useReducer } from 'react'; import reducer, { initalState } from './reducer.js'; function Counter() { const [state, dispatch] = useReducer(reducer, initialState); return ( <div> <button onClick={() => dispatch({type: 'increment'})}>+</button> <button onClick={() => dispatch({type: 'decrement'})}>-</button> </div> ); }
4.useContext
接收一個 context 對象(React.createContext 的返回值)並返回該 context 的當前值。當前的 context 值由上層組件中距離當前組件最近的 <MyContext.Provider> 的 value prop 決定。component
具體使用查看這篇文章。