不久前,react在新的16.7.0-alpha.0版本中推出了新的hooks函數,其做用就是讓你能夠不用類組件就可使用react的state和其餘功能。你們都知道,class的寫法有的時候很繁瑣,好比其中的this問題等等。本篇文章主要介紹函數包括這幾個useState
、useEffect
、useContext
、useRef
,這篇文章主要介紹一下這些函數的做用。javascript
好比說有一個組件須要內部維護本身的狀態,以前咱們寫class組件的話通常都是定義一下state,而後須要修改的時候,用setState去修改自身的狀態。useState這個函數就是起到了這個做用,接受一個參數initialState
,也就是初始的state,同時返回一個數組,第一個是當前的state,第二個就是至關於之前class組件的setState,每次調用這個函數都會更新state同時讓當前組件從新渲染一遍,看一下簡單的count計數器用hooks怎麼寫html
function Cunter() {
const [count, setCount] = useState(0);
const [title, setTitle] = useState('hello-react');
console.log('render ===============');
return (
<div className="count-box"> <h1 className="title">點了{count}次</h1> <button onClick={() => { setCount(count + 1); setTitle('hello-hooks'); }}> Click Me! </button> <p>{title}</p> </div>
)
}
複製代碼
上面這個組件在點擊button後,打開控制檯看到兩次更改狀態只render了一次,因此這裏的useState也是會將一次循環中的state變化合並,而後一塊兒更新。 同時在function組件中,useState能夠調用屢次,但不意味着必定要這樣寫,固然,initialState能夠是數組也能夠是對象,因此你能夠在一次set函數中直接修改像class組件中調用setState同樣,不過這樣寫的話,我以爲語義更加清晰。java
使用這個函數你能夠通知react在當前組件每次渲染完成以後須要完成什麼動做,我以爲其做用能夠理解爲與以前的componentDidMount
和componentDidUpdate
兩個生命週期函數相似。 這個函數支持兩個參數,第一個參數是一個函數,會在每次render以後執行,同時這個函數也能夠返回一個函數,這個函數會在組件卸載後執行,相似於類組件的componnentDidUnmount
生命週期函數。 舉個例子,好比說咱們想實時獲取窗口的寬度,而後在這個組件被卸載的時候取消這個功能。看下代碼react
function Width() {
const [width,setWidth] = useState(window.innerWidth);
const setWidthFn = () => {
setWidth(window.innerWidth);
};
useEffect(() => {
window.addEventListener('resize',setWidthFn);
return () => {
window.removeEventListener('resize',setWidthFn)
}
});
return(
<div> <h1>當前窗口寬度{width}px</h1> </div>
)
}
複製代碼
可是這樣也有缺點,就是每次render的時候都會執行一遍這個函數,有的時候咱們並不但願都去執行,好比說一個詳情組件在第一次render的時候會跟根據props傳遞過來的id去取值,若是這樣寫的話,每一次props改變的時候都會引起組件,從新請求一遍,不過,react已經幫咱們作好了處理,咱們能夠給useEffect函數傳遞第二個參數,****** 這樣,請求詳情的這個函數就只會在id改變的時候執行,因此這裏的代碼能夠這樣寫。redux
function SomeComponent({id}){
useEffect(() => {
doSomethingWith(id)
/* 固然,第二個參數能夠傳遞進不僅一個依賴項,這樣就是告訴React多個依賴項有一個發生變化就會從新執行這個函數。 也能夠傳遞進一個空數組,這樣是告訴React這個函數只執行一次。 具體爲何要傳遞進去數組,官網文檔上沒有看到相關的解釋。 */
},[id])
}
複製代碼
這個函數一樣會接受一個initialState做爲參數,同時返回一個對象,其中的current就是你當前傳遞進去的initialState,你能夠把返回的對象做爲ref屬性,傳遞給子組件來獲取DOM對象,同時你也能夠用它來保存previousProps,用法以下:數組
function Counter() {
const [count, setCount] = useState(0);
const prevCountRef = useRef();
useEffect(() => {
prevCountRef.current = count;
});
const prevCount = prevCountRef.current;
return (
<div> <h1>Now: {count}, before: {prevCount}</h1> <button onClick={setCount(count + 1)}>Click Me!</button> </div>
)
}
複製代碼
用法很簡單,將React.createContext返回的結果傳入useContext便可,同時context改變的時候也會引起該組件從新渲染。函數
這個函數簡直和redux如出一轍了,很少介紹。學習
本來class組件中對於state的變化、修改,咱們很難能夠把關於state的邏輯抽象出來,實現複用,可是基於hooks函數,你就徹底能夠作到這一點。同時,React官網也說了useYourImagination,因此具體如何複用要結合實際項目進行抽離。ui
getSnapshotBeforeUpdate
和componentDidCatch
,可是不能在class函數組件中使用,同時也不建議一個項目裏面二者混用,保持團隊的一致性。最後引用一下Dan在React Conf上關於Hooks的演講,簡單翻譯一下。this
我開始學習react的時候就想過React的logo和react有什麼關係,這個項目也不叫作Atom(原子),也不是一個物理引擎,其中的一個解釋是基於reaction(反應)的,化學反應就是基於原子在其中的表現,因此叫react。可是,我發現了一個更合理的解釋,我以爲是這樣,原子的種類和屬性決定了物理反應的表現和形態,react讓我知道了你能夠把用戶界面分離成一個個獨立的個體,這個個體叫作組件,這些組件的屬性和種類決定了用戶界面的外觀和特效。但是搞笑的是,Atom這個詞的自己含義就是不可分離的,當科學家們第一次發現原子的時候,他們覺得這就是最小的物質,但不久他們就發現了電子,電子就是原子中更小的一部分,電子對原子如何表現進行了更深一層的解釋。我以爲hooks就像是電子同樣,他不是一個新的功能,他只是讓我可以使用那些react已知的功能,好比說state(狀態),context(上下文),life cycle生命週期函數,hooks是react一種更直接的表達方式,更好的解釋了組件如何在內部工做的,我以爲這些已經隱藏了長達四年久,如今你看一下react的logo,你能夠看到那些電子的運動軌道,因此說hooks可能就一直存在,就像logo上的電子軌道同樣。