忽然發現上一篇文章已是半年以前了,最近一直在沉迷工做,天天就到掘金看看漲漲姿式。可是領導最近忽然跟我說你hooks用的挺多的嘛,要不作個組內技術分享吧。因此又撿起了筆頭寫了一個相似普及Hooks的文章= =html
話說回來,如今我已經再也不使用class 組件(除非一些舊項目 或者 對function component支持度不夠,如 Taro 編寫小程序),而是全面擁抱 hooks ,統一使用函數組件,寫代碼效率提升了很多。react
根據個人實踐和對hooks的理解,它帶給我最大的感覺就是:小程序
官方文檔:React Hooks中文簡介數組
下面我將會經過實現一個最多見的帶篩選項的列表頁,來跟你們分享如何使用hooks來編寫咱們的代碼,實現咱們的功能。bash
頁面原型 網絡
使用data和filters搭配Immutable保存列表和篩選項數據,useState函數參數爲state初始值。antd
import { fromJS } from 'immutable';
import { Table } from 'antd'; // 基礎組件基於阿里antd組件庫
function TablePage() {
const [data, setData] = useState([]);
const [filters, setFilters] = useState(fromJS({
deliveryTime: [],
orderTime: [],
name: '',
}));
return (
<div>
<Filters /> {/*Filters爲具體的篩選組件,這裏略過*/}
<Table
dataSource={data}
/>
</div>
);
}
複製代碼
useEffect在我看來是最重要的hooks,它給予了咱們在組件渲染後實現各類不一樣的反作用的手段。官方文檔介紹useEffect能夠看做是componentDidMount,componentDidUpdate 和 componentWillUnmount 這三個函數的組合。因此effect在每一次渲染更新(包括第一次)後都會執行。函數
這就帶來另一個問題,如何控制useEffect的執行,因此useEffect的第二個參數這時候就發揮了做用,它提供了useEffect是否執行的依據。每次執行useEffect以前,React會判斷參數中的每一個依賴是否與上次渲染的值是否一致,若一致就會跳過執行effect,這就達到了控制的效果。post
// 當咱們想effect僅執行一次的時候,可傳入一個空數組,表示該effect不依賴於任何state或者props
useEffect(() => {
effect1();
}, []);
// 在列表頁中,咱們須要在filters改變的時候執行獲取數據的effect,此時immutable的特性就能夠發揮出來
// 對於引用類型,每次函數執行時都至關因而一個新值,因此傳入引用類型的依賴是錯誤的,而Immutable的特性容許咱們傳入整個filters
useEffect(() => {
getData(); // 獲取數據的函數,依賴於filters的值
}, [filters]);
複製代碼
因此咱們如今的頁面代碼看起來就像這樣:fetch
function TablePage() {
const [data, setData] = useState([]);
const [filters, setFilters] = useState(fromJS({
deliveryTime: '',
orderTime: '',
name: '',
}));
useEffect(() => {
getData(); // 獲取數據的函數,依賴於filters的值
}, [filters]);
function getData() { // 一個經過網絡請求獲取數據的函數
fetchAPI({
deliveryTime: filters.get('deliveryTime'),
orderTime: filters.get('orderTime'),
name: filters.get('name'),
})
.then((rsp) => {
setData(rsp.data);
});
}
function handleFiltersChange(key, value) {
setFilters(filters.set(key, value);
}
return (
<div>
<Filters onChange={handleFiltersChange} /> {/*Filters爲具體的篩選組件,這裏略過*/}
<Table
dataSource={data}
/>
</div>
);
}
複製代碼
在平常開發中,咱們會有不少不少的邏輯實際上是重複的,當咱們想在兩個函數之間共享邏輯時,咱們會把它提取到第三個函數中。而組件和 Hook 都是函數,因此也一樣適用這種方式。這第三個函數就是咱們的自定義Hook。
自定義 Hook 是一個函數,其名稱以 「use」 開頭且必須以 「use」 開頭;函數內部能夠調用其餘的 Hook,且其內部的Hook是徹底獨立的。
function usePagination(paginationOptions) {
const [_pagination, setPagination] = useState(fromJS({
total: 0,
current: 1,
pageSize: 10,
...paginationOptions,
}));
return [_pagination, setPagination];
}
複製代碼
function useDebounce() {
const [timer, setTimer] = useState(0);
function debounce(throttleFunc, ThrottleTime = 250) {
clearTimeout(timer);
setTimer(setTimeout(throttleFunc, ThrottleTime));
}
return debounce;
}
複製代碼
這時列表頁面中能夠像以下這樣使用咱們的自定義hooks:
function TablePage() {
const [data, setData] = useState([]);
const [filters, setFilters] = useState(fromJS({
deliveryTime: '',
orderTime: '',
name: '',
}));
const [pagination, setPaination] = usePagination();
const debounce = useDebounce(); // 獲取debounce函數
useEffect(() => {
debounce(getData); // 獲取數據的函數,依賴於filters的值
}, [filters]);
function getData() { // 一個經過網絡請求獲取數據的函數
fetchAPI({
deliveryTime: filters.get('deliveryTime'),
orderTime: filters.get('orderTime'),
name: filters.get('name'),
})
.then((rsp) => {
setData(rsp.data);
});
}
function handleFiltersChange(key, value) {
setFilters(filters.set(key, value);
}
function handleTableChange(_pagination) {
setPaination(
pagination.set('current', _pagination.current)
.set('pageSize', _pagination.pageSize)
);
}
return (
<div>
<Filters onChange={handleFiltersChange} /> {/*Filters爲具體的篩選組件,這裏略過*/}
<Table
columns={/* wirte your own columns config */}
dataSource={data}
onChange={handleTableChange}
/>
</div>
);
複製代碼
想了解更多自定義hooks的玩法,能夠了解一下如下文章:
2019年了,整理了N個實用案例幫你快速遷移到React Hooks
React hooks 的嘗試使用 (個人關於hooks的上一篇文章,包括useContext合useReducer的一些使用和一些自定義hooks)
這樣咱們基本上就實現了一個用Hooks管理的函數組件了,可能這一個簡單的案列還不能徹底體現hooks的優點,還有一些優化手段諸如useMemo和useCallback搭配HOC,還有最近在使用的TypeScript,這些咱們之後有機會再講。最後歡迎你們給我提意見,多交流,讓咱們在掘金共同進步!