原文地址:博客html
React 16.8版本發佈於2019年2月6號,它帶來了Hooks特性,可以讓咱們不編寫class的狀況下也能使用state以及其餘的React特性。一個新技術的誕生必然會影響原來的思惟模式,在最初的應用中也會遇見不少意想不到的場景和陷阱,這就須要咱們在使用他們前清楚的知道哪裏可能會有潛在的問題,有哪些更加完善的寫法,這也是寫本文章的初衷。咱們團隊在7月份開始在新項目中全面使用Hooks技術,期間也遇到和解決了不少的麻煩和問題,同時讓咱們對於函數式組件有了更深的理解。react
在本文開始前,須要你掌握React官方中關於React Hooks的基礎知識。不少坑在官方的FAQ已經說明了,常常閱讀官方文檔也是個良好的習慣。後端
本文介紹的是我在使用Hooks的過程當中碰見的問題和技巧,可能還有其餘我沒發現的或者沒有寫出來的,歡迎和我交流,但願經過閱讀本文可以讓你快速的掌握Hooks的陷阱和技巧,開發出高質量的函數式組件。那咱們就先從useState
開始。數組
在Class Component中,使用state來存儲組件的狀態,用setState
來更新,在Hooks中提供了useState
API來建立一個state。閉包
useState
接收一個initialState,同時返回一個state以及更新state的函數。initialState可使用基礎數據類型,也可使用數組、對象等引用數據類型。這裏建議根據state的關聯度和做用來決定是否使用多個useState
來定義state。函數
在下面的例子中,咱們根據後端接口返回的數據{data: [Tom, Jerry], total: 2, result: true}
來設置state數據。第一種寫法直接將全部的請求參數和返回數據所有存儲到一個userState
中,咱們來分析下爲什麼不推薦這麼作。oop
首先,返回的數據中存在不須要存儲在state中的數據字段result。其次,將data與requestParams放在一個state中看似簡單,只須要維護一個userState
,可是若是須要在useEffect
中依賴data
或者requestParams
將會很是的麻煩,並且每次獲取後端返回的數據都將須要一同更新requestParams
。優化
不建議的寫法ui
const [userState, setUserState] = useState({
data: [],
total: 0,
requestParams: { id: 1 },
result: true
})
複製代碼
推薦的寫法spa
const [userData, setUserData] = useState({ data: [], total: 0 })
const [userParams, setUserParams] = useState({ id: 1 })
複製代碼
若是initialState爲函數,則useState
在初始化時會馬上執行該函數和獲取函數的返回值,在沒有任何返回值得狀況下爲undefined
。這裏須要注意的是每次組件re-render都會致使useState
中的函數從新計算,這裏可使用閉包函數來解決問題。在優化後只有組件初始化時纔會執行一遍loop
函數。
本例子能夠在CodeSandbox中查看
優化前
const loop = () => {
console.log("calc!");
let res = 0;
for (let i = 0, len = 1000; i < len; i++) {
res += i;
}
return res;
};
const [value, setValue] = useState(loop());
複製代碼
優化後
const App = () => {
const [value, setValue] = useState(() => {
return loop();
});
}
複製代碼
在某些狀況下若是須要從上一個state來計算當前的state,可能會想到使用下面優化前的方法。可是,須要注意的一點是在某些閉包的場景下面count
可能不是最新的,這樣會致使計算錯誤。這裏推薦使用官方給出的方法。
優化前
function Counter() {
const [count, setCount] = useState(0);
return <button onClick={() => setCount(count + 1)}>+</button>
}
複製代碼
優化後
function Counter() {
const [count, setCount] = useState(0);
return <button onClick={() => setCount(prevCount => prevCount + 1)}>+</button>
}
複製代碼
下一篇文章介紹useEffect
和useLayoutEffect
的使用技巧。