在本文結束時,您將可以回答如下問題:react
Hooks 能夠作到如下事情:json
若是你已經使用過React,你就會知道複雜多變,有狀態的邏輯是如何獲得的,當應用程序爲功能添加了幾個新功能時,就會發生組件代碼變得複雜而難以維護這種狀況。爲了嘗試簡化這個問題,React背後的大腦試圖找到解決這個問題的方法。數組
(1) 在組件之間重用有狀態邏輯架構
hooks容許開發人員編寫簡單,有狀態的功能組件,並在開發時花費更少的時間來設計和重構組件層次結構。怎麼樣?使用鉤子,您能夠在組件之間_獲取_和_分享_有狀態邏輯。框架
(2) 簡化組件邏輯函數
當您的應用程序中出現不可避免的指數級邏輯增加時,簡單的組件就回由於各類狀態邏輯和生命週期等等因素,而變得繁瑣和複雜。組件的職責增加並變得不可分割。反過來,這使編碼變得麻煩而且測試困難。工具
class是React架構的重要組成部分。class有許多好處,但它們爲初學者創造了入門的障礙。對於class,您還必須記住將this綁定到事件處理程序,所以代碼可能變得冗長且有點多餘。post
React版本 16.8.學習
import { useState, useEffect } from 'react';
很簡單,但你如何實際使用這些新方法?如下示例很是簡單,但這些方法的功能很是強大。測試
使用狀態鉤子(state hook)的最好方法是對其進行解構並設置原始值。第一個參數將用於存儲狀態,第二個參數用於更新狀態。
例如:
const [weight, setWeight] = useState(150); onClick={() => setWeight(weight + 15)}
weight是狀態
setWeight是一種用於更新狀態的方法
useState(150)是用於設置初始值(任何基本類型)的方法
值得注意的是,您能夠在單個組件中屢次構造狀態hook:
const [age, setAge] = useState(42); const [month, setMonth] = useState('February'); const [todos, setTodos] = useState([{ text: 'Eat pie' }]);
所以,該組件可能看起來像:
import React, { useState } from 'react'; export default function App() { const [weight, setWeight] = useState(150); const [age] = useState(42); const [month] = useState('February'); const [todos] = useState([{ text: 'Eat pie' }]); return ( Current Weight: {weight} Age: {age} Month: {month} setWeight(weight + 15)}> {todos[0].text} ); }
使用effect hook 就好像使用componentDidMount, componentDidUpdate, 和 componentWillUnmount這類的生命週期的方法。
例如:
// similar to the componentDidMount and componentDidUpdate methods useEffect(() => { document.title = You clicked ${count} times; });
組件更新的任什麼時候候,渲染後都會調用useEffect。如今,若是你只想在變量count改變時更新useEffect,你只需將該事實添加到數組中方法的末尾,相似於高階reduce方法末尾的累加器。
// check out the variable count in the array at the end... useEffect(() => { document.title = You clicked ${count} times; }, [ count ]);
讓咱們結合兩個例子:
const [weight, setWeight] = useState(150); useEffect(() => { document.title = You weigh ${weight}, you ok with that?; }, [ weight ]); onClick={() => setWeight(weight + 15)}
所以,當觸發onClick時,也會調用useEffect方法,並在DOM更新後在文檔標題中呈現新的數據。
例:
import React, { useState, useEffect } from 'react'; export default function App() { const [weight, setWeight] = useState(150); const [age] = useState(42); const [month] = useState('February'); const [todos] = useState([{ text: 'Eat pie' }]); useEffect(() => { document.title = You weigh ${weight}, you ok with that?; }); return ( Current Weight: {weight} Age: {age} Month: {month} setWeight(weight + 15)}> {todos[0].text} ); }
useEffect很是適合進行API調用:
useEffect(() => { fetch('https://jsonplaceholder.typicode.com/todos/1') .then(results => results.json()) .then((data) => { setTodos([{ text: data.title }]); }); }, []);
React鉤子看起來很棒,可是若是你花一點時間,你可能會意識到在多個組件中從新初始化多個鉤子方法,好比useState和useEffect,可能會違背DRY(Don't repeat yourself)原則。那麼,讓咱們看看如何經過建立自定義鉤子來重用這些新內置方法。
是的,React鉤子有規則。這些規則乍一看彷佛是很是規的,可是一旦你理解了React鉤子如何啓動的基礎知識,規則就很容易理解。
(1) 必須在頂層以相同的順序調用掛鉤。(依次調用)
Hooks建立一個鉤子調用數組來保持秩序。這個命令有助於React告訴區別,例如,在單個組件中或跨應用程序的多個useState和useEffect方法調用之間。
例如:
// This is good! function ComponentWithHooks() { // top-level! const [age, setAge] = useState(42); const [month, setMonth] = useState('February'); const [todos, setTodos] = useState([{ text: 'Eat pie' }]); return ( //... ) }
在第一次渲染時,42,February,[{text:'Eat pie'}]都被推入狀態數組。
當組件從新渲染時,忽略useState方法參數。
age,month和todos的值是從組件的狀態中檢索的,這是前面提到的狀態數組。
(2) 沒法在條件語句或循環中調用掛鉤。
因爲啓動hooks的方式,不容許使用within條件語句或循環。對於hooks,若是在從新渲染期間初始化的順序發生變化,則極可能您的應用程序沒法正常運行。您仍然能夠在組件中使用條件語句和循環,但不能在代碼塊內使用鉤子。
例如:
// DON'T DO THIS!! const [DNAMatch, setDNAMatch] = useState(false) if (name) { setDNAMatch(true) const [name, setName] = useState(name) useEffect(function persistFamily() { localStorage.setItem('dad', name); }, []); } // DO THIS!! const [DNAMatch, setDNAMatch] = useState(false) const [name, setName] = useState(null) useEffect(() => { if (name) { setDNAMatch(true) setName(name) localStorage.setItem('dad', name); } }, []);
(3) 鉤子不能用在class組件中。
鉤子必須在功能組件或自定義鉤子函數中初始化。自定義鉤子函數只能在功能組件中調用,而且必須遵循與非自定義鉤子相同的規則。
您仍然能夠在同一個應用程序中使用類組件。您可使用hooks做爲類組件的子項呈現功能組件。
(4) 自定義鉤子應該以單詞use開頭而且是駝峯式的。
這是一個強有力的建議而非規則,但它將有助於您的應用程序的一致性。你也會知道,當你看到一個以「use」爲前綴的函數時,它多是一個自定義鉤子。
自定義掛鉤只是遵循與非自定義掛鉤相同規則的函數。它們容許您整合邏輯,共享數據以及跨組件重用鉤子。
當您須要在組件之間共享邏輯時,最好使用自定義掛鉤。在JavaScript中,當您想要在兩個單獨的函數之間共享邏輯時,您能夠建立另外一個函數來支持它。好吧,就像組件同樣,hooks也是function。您能夠提取hooks邏輯,以便在應用程序的組件之間共享。在編寫自定義hooks時,您能夠命名它們(再次以「use」開頭),設置參數,並告訴它們應該返回什麼(若是有的話)。
例如:
import { useEffect, useState } from 'react'; const useFetch = ({ url, defaultData = null }) => { const [data, setData] = useState(defaultData); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); useEffect(() => { fetch(url) .then(res => res.json()) .then((res) => { setData(res); setLoading(false); }) .catch((err) => { setError(err); setLoading(false); }); }, []); const fetchResults = { data, loading, error, }; return fetchResults; }; export default useFetch;
Hooks容許您在應用程序增加時抑制複雜性,並編寫更易於理解的代碼。下面的代碼是兩個具備相同功能的組件的比較。在第一次比較以後,咱們將在伴隨容器的組件中使用自定義鉤子展現更多好處。
如下類組件應該看起來:
import React from 'react'; class OneChanceButton extends React.Component { constructor(props) { super(props); this.state = { clicked: false, }; this.handleClick = this.handleClick.bind(this); } handleClick() { return this.setState({ clicked: true }); } render() { return ( You Have One Chance to Click ); } } export default OneChanceButton;
如何使用鉤子實現相同的功能來簡化代碼並提升可讀性:
import React, { useState } from 'react'; function OneChanceButton(props) { const [clicked, setClicked] = useState(false); function doClick() { return setClicked(true); } return ( You Have One Chance to Click ); } export default OneChanceButton;
React hooks是一個驚人的新功能!實施的理由是合理的;而且,再加上這一點,我相信這將極大地下降React編碼的門檻,並使其保持在最喜歡的框架之上列表。看到這會如何改變第三方庫的工做方式,尤爲是狀態管理工具和路由器,將會很是使人興奮。
總之,React鉤子:
推薦閱讀: https://juejin.im/post/5be8d3...