react-redux使用hooks替代connect

前言

redux的經典使用方式就是通過高階組件connect來將組件和store關聯起來,我們見過最多的場景也是connect和類組件的組合使用(也可以和函數組件配合使用)。但在擁抱hooks的今天,我們如何拋棄connect,通過hooks獲取到狀態和dispatch呢?

react-redux中的hook

在react-redux7.1版本之後(如果你的版本比較低又不能升級版本,可以忽略本文)正式推出了三個hook: useDispatch, useSelectoruseStore。這些hooks分別用於獲取dispatch獲取狀態獲取store對象。接下來我們來對比一下之前的寫法和hook的寫法。

1. connect版

import actions from 'xxx';
class Foo extends React.Component {
	componentDidMount() {
		const { dispatch } = this.props;
		dispatch(getData());		// 請求數據
	}

	renderData() {
		const { data } = this.props; // 獲取數據
		return (
			...
		)
	}

	render() {
		<div>
			{ this.renderData() }
		</div>
	}
}

function mapStateToProps(state) {
    return { data: state.data };
}

export default connect(
	mapStateToProps, 			 // state
	{ getData: actions.getData } // actions
)(Foo);

2. hook版

本示例中只用到了useSelector和useDispatch,因爲這兩個是在組件中最常用的,useStore則要在你需要使用store對象的地方使用。

import actions from 'xxx';
import React, { useEffect } from 'react';
import { useDispatch, useSelector } from 'react-redux';

function Foo(props) {
	const dispatch = useDispatch();
	const data = useSelector(state => state.data);

	useEffect(() => {
		dispatch(actions.getData());
	}, [ dispatch ]);

	const renderData = () => {
		return (
			...
		);
	};

	return (
		<div>
			{ renderData() }
		</div>
	)
}

export default Foo;

3. useStore的使用方法

import { useStore } from 'react-redux';

function Foo(props) {
	const store = useStore();
	const state = store.getState();
	...
}

注意

useSelector接收兩個參數: selectorequalityFn。第一個參數就像上面示例中一樣,傳入一個函數以獲取你想要的state。第二個參數也是個函數,用於比較狀態是否發生改變,如果這個函數的執行結果爲false就表示狀態發生改變,組件將重新渲染。useSelector源碼是這樣的:

function useSelector(selector, equalityFn = refEquality) {
 	invariant(selector, `You must pass a selector to useSelectors`);
 	
 	const { store, subscription: contextSub } = useReduxContext();
 
 	return useSelectorWithStoreAndSubscription(
        selector,
        equalityFn,
        store,
        contextSub
    )
}

我們可以看到有個默認值refEquality, 這個函數非常簡單:

const refEquality = (a, b) => a === b

這個函數你可以自定義,react-redux也提供了一個現成的淺比較方法shallowEqual,這個就和connect比較state的方式很類似了,你可以這麼用:

import { useSelector, shallowEqual } from 'react-redux';
const data = useSelector(state => state.data, shallowEqual);
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章