最近組內大佬給小編安排了一個任務,整理一份關於react-hooks
的簡單的使用教程。javascript
看到消息的時候有點欣喜,由於小編以前就想整理,奈何抵不過惰性,正好趁着此次機會,把hooks
相關的知識點學習並鞏固一下(雖然沒有用過,可是期待在之後的項目中嘗試)。 java
這篇文章會圍繞hook
的特性以及基本使用方式,State hook
,Effect hook
,useContext
以及自定義hook展開,有興趣的童鞋能夠停下腳步,稍微瞭解一下。react
首先,咱們須要知道的是,hook
是react
16.8的新增特性,他的最特別的一點就是命名的時候必定要以use
開頭。不要問我爲何,多是爲了便於識別是否爲hooks
的一種手段吧。數組
在這裏,不得不說一下linter
這個插件,這是專門用來檢查hook格式的一個插件,pick它吧。bash
其次,hook
是一些可讓你在函數組件內「鉤入」 React state
以及生命週期等特性的函數。(例如,useState
是容許你在 React
函數組件中添加 state
的 Hook
)hook
不能在class
組件中使用,這就使得咱們在不寫class
組件時,也能使用hook。網絡
最後,hook
100%向下兼容。hook也能夠將組件中相互關聯的部分拆分紅更小的函數(好比設置訂閱,請求數據等)。app
⚠️hook
就是javascript
函數,可是使用其有兩個額外的原則:ide
1.只能在函數最外層調用hook
;函數
2.只能在react
的函數組件中調用hook
;學習
3.不要在循環,條件或嵌套以及普通的javascript
中調用hook
;
首先,看官網給的一個比較簡單的計數器示例:
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
,而後聲明瞭一個初始值爲0的count
的變量,經過setCount
這個方法去直接改變count
的值。
這裏的onClick={() => setCount(count + 1)}
在沒有hook
以前,能夠理解爲onClick={this.setcount}
,而後在聲明的setCount
方法內進行this.setState({count: count + 1})
操做。
以上能夠看出,使用hook
方便不少,在精簡了代碼的基礎上,還能夠去掉傳統this指向等繁瑣的問題。
咱們再來看另外一個配合ant design使用的例子:
function Example() {
const [open, setOpen] = useState(false);
return (
<>
<Button type="primary" onClick={() => setOpen(true)}>
Open Modal
</Button>
<Modal
visible={open}
onOk={() => setOpen(false)}
onCancel={() => setOpen(false)}
/>
</>
);
}
複製代碼
拓展一下,咱們能夠經過給按鈕設置初始值來控制彈窗的彈出與關閉等等。
使用useState
時,咱們須要知道的總結一下大概有如下幾點:
1.state
是隻讀的;
2.useState
函數的第一個參數,是state
變量的初始值;
3.每次進行渲染時,多個State Hook
的順序、數量都必須同樣;
4.state
變量發生變化時,會觸發新的渲染;state
變量沒變化,不觸發新的渲染;
使用state hook
的主要做用就是獲取須要的 state
和 更新state
的方法,以官網例子爲例:
const [state, setState] = useState(initialState);
複製代碼
參數: initialState
能夠做爲state
的一個初始值,同時,他也能夠是一個函數,返回值做爲state
的初始值,該參數只會在初始渲染時起做用。
返回值: 會返回一個數組,一個是state
的值,另外一個是更新state
值的一個方法。(這裏的setState
不會合並state
的值)。
若是要定義多個變量,能夠屢次使用useState
。
小編以爲,官網關於state hook
部分有一個小技巧值得一提,以下:
var fruitStateVariable = useState('banana'); // 返回一個有兩個元素的數組
var fruit = fruitStateVariable[0]; // 數組裏的第一個值
var setFruit = fruitStateVariable[1]; // 數組裏的第二個值
複製代碼
使用數組解構來將定義的變量經過[0],[1],解構到原來setState
返回的兩個值的數組當中。
數據獲取,設置訂閱以及手動更改 React
組件中的 DOM
都屬於反作用。Effect Hook
可讓咱們在函數組件中經過使用useEffect
提高操做反作用的能力,它在渲染以後執行,咱們能夠把它看作 componentDidMount
,componentDidUpdate
和componentWillUnmount
這三個函數的組合。
簡單的理解就是:useEffect
跟以上三個生命週期用途相同,只不過被合併成了一個API
。
在使用useEffect
的時候,須要考慮兩點:須要清除和不須要清除。那麼什麼狀況下須要清除,什麼狀況下又不須要清除呢?小編帶你來了解
當訂閱外部數據源的時候,須要清除數據。數據須要清除,能夠返回一個函數。
以官網的例子爲例:
import React, { useState, useEffect } from 'react';
function FriendStatus(props) {
const [isOnline, setIsOnline] = useState(null);
useEffect(() => {
function handleStatusChange(status) {
setIsOnline(status.isOnline);
}
ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);
// Specify how to clean up after this effect:
return function cleanup() {
ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
};
});
if (isOnline === null) {
return 'Loading...';
}
return isOnline ? 'Online' : 'Offline';
}
複製代碼
爲了避免會引發內存泄漏,訂閱外部數據源時須要清除數據。effect
返回一個函數是由於這是effect
可選的清除機制,同時,React
會在組件卸載的時候執行清除操做。
固然,在hook
還沒出來以前,使用class建立組件訂閱外部數據源時,清除方式以下(此處依舊引用官網代碼):
class FriendStatus extends React.Component {
constructor(props) {
super(props);
this.state = { isOnline: null };
this.handleStatusChange = this.handleStatusChange.bind(this);
}
componentDidMount() {
ChatAPI.subscribeToFriendStatus(
this.props.friend.id,
this.handleStatusChange
);
}
componentDidUpdate(prevProps) {
// 取消訂閱以前的 friend.id
ChatAPI.unsubscribeFromFriendStatus(
prevProps.friend.id,
this.handleStatusChange
);
// 訂閱新的 friend.id
ChatAPI.subscribeToFriendStatus(
this.props.friend.id,
this.handleStatusChange
);
}
componentWillUnmount() {
ChatAPI.unsubscribeFromFriendStatus(
this.props.friend.id,
this.handleStatusChange
);
}
handleStatusChange(status) {
this.setState({
isOnline: status.isOnline
});
}
render() {
if (this.state.isOnline === null) {
return 'Loading...';
}
return this.state.isOnline ? 'Online' : 'Offline';
}
}
複製代碼
當使用class建立一個組件,而且使用了componentDidMount
訂閱,在componentDidUpdate
中更新訂閱,在componentWillUnmount
清除。
能夠看到,較使用effect
來講,class
清除反作用時代碼較爲冗餘。
當effect
內只有單行代碼,或者咱們只想在React
更新DOM
以後運行一些額外的代碼。好比發送網絡請求,手動變動 DOM
,記錄日誌,這些無需清除的操做。 如官網代碼所示:
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>
);
}
複製代碼
這種狀況下無需清除反作用。
還有一點咱們應該要注意的是,咱們須要跳過一些沒必要要反作用函數。那麼,如何才能跳過呢?這裏就要講到useEffect
的第二個參數。
咱們須要給useEffect
的傳入第二個參數,當第二個參數改變時,執行反作用;當參數不改變時,可直接跳過反作用不執行。例子以下:
useEffect(() => {
document.title = `You clicked ${count} times`;
}, [count]); // 當count的值更新時,纔會從新執行`document.title`
複製代碼
咱們先來看個例子:
import React from 'react';
const appContext = React.createContext(); //建立一個context
functuion App() {
return (
<appContext.Provider value={888}> //這使用了Provider主要是爲全部後代提供value值
<div>
<Show />
</div>
</appContext.Provider>
)
}
function Show() {
return (
<appContext.Consumer> //使用Consumer獲取到value的值
{value => <div>{value}</div>}
</appContext.Consumer>
)
}
複製代碼
首先咱們能夠看到,使用contextAPI
的方式下,能夠經過建立一個context
上下文,返回一個帶有{Provider, Consumer}
的值的對象,而後經過使用Provider
主要是爲全部後代提供value
值,這避免了以往手動一個個向子孫組件傳遞prop
。
而後,可使用Consumer
能夠從上下文獲取value的值。須要注意的一點是,這個Consumer
子組件,在這裏只能是惟一的一個函數。
再來看一下使用useContext的狀況
import React, { useContext } from 'react';
const appContext = React.createContext(); //建立一個context
functuion App() {
return (
<appContext.Provider value={888}> //這使用了Provider主要是爲全部後代提供value值
<div>
<Show />
</div>
</appContext.Provider>
)
}
function Show() {
const apps = useContext(appContext);
return (
{value => <div>{apps}</div>}
)
}
複製代碼
這裏調用useContext
,傳入從React.createContext()
獲取到的上下文對象。須要注意的一點是,useContext
的參數必須是 context
對象自己,即useContext(appContext)
,而不是useContext(appContext.Provider)
或useContext(appContext.consumer)
。
前面已經講到,hook
通常以use
開頭,自定義hook也同樣。自定義 hook
是一個函數,其名稱以 use
開頭(必須),函數內部能夠調用其餘的hook
。
當項目中,咱們想要共享組件之間的狀態邏輯時,最多見的方法是使用高階組件
或者 render props
。可是,使用自定義的hook
能夠是你在不增長組件的前提之下,把公用邏輯提取出來進行復用。
(詳情可查看官網:react.docschina.org/docs/hooks-…)
以上就是小編此次對於react-hooks知識點的一個大概的梳理,如有錯誤,歡迎指出,一塊兒學習,一塊兒進步。(若覺尚可,可暗戳戳筆芯)