此文章只是整理了在 React 項目開發中經常使用的一些 Hooks,具體每一個的坑,以及詳細解刨後續繼續更新,並會加上連接。javascript
Hooks 只能用於函數組件當中。html
import React, { useState } from 'react';
const Component = () => {
const [count, setCount] = useState(0);
return (
<button onClick={() => setCount(count + 1)}>click<button>
)
}
複製代碼
此方法會返回兩個值:當期狀態和更新狀態的函數。效果同 this.state
與 this.setState
,區別是 useState
傳入的值並不必定要對象,而且在更新的時候不會吧當前的 state 與舊的 state 合併。java
import React, { useState, useEffect } from 'react';
let timer = null;
const Component = () => {
const [count, setCount] = useState(0);
// 相似於 class 組件的 componentDidMount 和 componentDidUpdate:
useEffect(() => {
document.title = `You clicked ${count} times`;
timer = setInterval(() => {
// events ...
}, 1000)
return () => {
// 相似 componentWillUnmount
// unmount events ...
clearInterval(timer); // 組件卸載 移除計時器
};
}, [count]);
// ...
}
複製代碼
若是 useEffect
第二個參數數組內的值發生了變化,那麼 useEffect
第一個參數的回調將會被再執行一遍。react
import React, { useCallback } from 'react';
const Component = () => {
const setUserInfo = payload => {}; // request api
const updateUserInfo = useCallback(payload => {
setUserInfo(Object.assign({}, userInfo, payload));
}, [userInfo]);
return (
<UserCard updateUserInfo={updateUserInfo}/> ) } 複製代碼
useCallback 會在二個參數的依賴項發生改變後才從新更新,若是將此函數傳遞到子組件時,每次父組件渲染此函數更新,就會致使子組件也從新渲染,能夠經過傳遞第二個參數以免一些非必要性的渲染。web
在一些特殊狀況下傳遞此參數還能夠解決一些由靜態做用域致使的問題。redux
import React, { useMemo } from 'react';
const Component = () => {
const [count, setCount] = useState(0);
const sum = useMemo(() => {
// 求和邏輯
return sum;
}, [count]);
return <div>{sum}</div>
}
複製代碼
useMemo 的用法跟 useCallback 同樣,區別就是一個返回的是緩存的方法,一個返回的是緩存的值。上述若是依賴值 count 不發生變化,計算 sum 的邏輯也就只會執行一次,從而性能。api
這是以後更新的:useCallback 與 useMemo 詳解 歡迎閱讀。數組
import { shallowEqual, useSelector } from 'react-redux';
const Component = () => {
const userInfo = useSelector(state => state.userInfo, shallowEqual);
// ...
}
複製代碼
useSelector 的第二個參數是一個比較函數,useSelector 中默認使用的是 ===
來判斷兩次計算的結果是否相同,若是咱們返回的是一個對象,那麼在 useSelector 中每次調用都會返回一個新對象,因此因此爲了減小一些不必的 re-render
,咱們可使用一些比較函數,如 react-redux 自帶的 shallowEqual
,或者是 Lodash 的 _.isEqual()
、Immutable 的比較功能。緩存
import React, { useCallback } from 'react';
import { useDispatch } from 'react-redux';
const Compnent = () => {
const dispatch = useDispatch();
const clearUserInfo = useCallback(
() => dispatch({ type: 'clearUserInfo' }),
[dispatch]
);
return (
<button onClick={clearUserInfo}>click</buttn>
)
}
複製代碼
使用 dispatch
來調度操做,加上 useCallback
來減小沒必要要的渲染。react-router
import { useHistory } from 'react-router';
const Compnent = () => {
const history = useHistory();
return (
<button onClick={() => history.push('/home')}>go home</buttn>
)
}
複製代碼
import React, { useEffect } from 'react';
import { useLocation } from 'react-router';
const Compnent = () => {
const location = useLocation();
useEffect(() => {
// ...
}, [location])
return (
<button onClick={() => history.push('/home')}>go home</buttn>
)
}
複製代碼
URL一發生變化,他將返回新的 location
import { useParams, useEffect } from 'react-router';
const Component = () => {
const params = useParams();
const getUserInfo = () => {}; // request api
useEffect(() => {
// parms 的 uid 發生變化就會從新請求用戶信息
getUserInfo(params.uid);
}, [params.uid]);
// ...
}
複製代碼
useParams 返回 react-router 的參數鍵值對
import { useRouteMatch } from 'react-router';
const Component = () => {
const match = useRouteMatch('/login');
// ...
}
複製代碼
useRouteMatch 傳入一個參數 path
,用來判斷當前路由是否能匹配上傳遞的 path
,適用於判斷一些全局性組件在不一樣路由下差別化的展現。
使用 Hooks 能爲開發提高很多效率,但並不表明就要拋棄 Class Component,依舊還有不少場景咱們還得用到它,好比須要封裝一個公共的可繼承的組件...
參考