redux 多種觸發dispatch方式

[原文鏈接]https://blog.bam.tech/developper-news/4-ways-to-dispatch-actions-with-redux

redux 作爲js app的主要的狀態容器和react結合的非常多。架構設計上基於action的觸發機制,通過dispatch對應的action來修改狀態,而狀態的修改由統一的reducer來處理(爲什麼叫reducer呢,因爲每個都可以作爲reduce函數的參數來處理)如果對redux的原理還不怎麼熟悉,可以先讀下這篇文章,當然是因爲的,對應的中文是這篇

我們在這裏將重點放在了第一步,也就是如何dispatch分發一個action。接下來我們就來處理這個問題,同時儘量保證component組件與redux的解耦。

舉例來說吧,我們假定這樣一個服務場景:就是用戶要發送一個message到一個羣裏。我們首先要創建個form表單(這裏是MessageSending.js),另外還需要一個發送的按鈕,當點擊時將沃恩的消息發給對應的API後臺。

PS:在下面的所有例子中,規定action creators 就叫actions

方法1: 直接通過dispatch方法

dispatch函數作爲store對象的方法可以直接調用

// App.js
import { createStore } from 'redux';
import { MessageSending } from './MessageSending';
import reducer from './reducer';

const store = createStore(reducer);
class App extends React.Component {
 render() {
 <MessageSending store={store} />
 };
};

// MessageSending.js
import { sendMessage } from './actions';
// ...
this.props.store.dispatch(sendMessage(message))
// ...

方法2:使用react-redux

上面一種方法的缺點是component需要包含你的app邏輯,而redux的作者之一的Dan Abramov建議需要可以將邏輯connect到store裏面(詳情可以參見筆者翻譯的另一篇文章,同樣出自Dan Abramov,講述Container組件與Presentation組件的區分)。所以我們就來實現下,創建一個MessageSending.container.js文件,在其中調用connect方法,而其中第二個參數function mapDispatchToProps,將所有的action creators做了封裝,然後統一傳遞到組件中。

// MessageSending.container.js
import { connect } from 'react-redux';
import { sendMessage } from './actions';
import MessageSending from './MessageSending';

const mapDispatchToProps = {
 sendMessage,
};

export default connect(null, mapDispatchToProps)(MessageSending);

// MessageSending.js
// ...
this.props.sendMessage(message);
// ...
If you want to dispatch several actions in one method you can do like that:
import { connect } from 'react-redux';
import { sendMessage, navigateTo } from './actions';

const mapDispatchToProps = dispatch => ({
 sendMessage: messaga => {
 dispatch(sendMessage(message));
 dispatch(navigateTo({ routeName: 'messagesList' }));
 },
});

export default connect(null, mapDispatchToProps)(MessageSending);
// MessageSending.js
// ...
this.props.sendMessage(message);
// ...
});

方法3: 通過saga來dispatch action

如果想要按順序挨個執行多個異步的指令,同時還想保證狀態可讀,那麼就可以通過觸發一個saga來實現。在saga中可以在dispatch actions時帶上put效果,想要了解更多的信息可以查閱redux-saga的文檔

// sagas.js
import { put } from 'redux-saga/effects';
import { sendMessage, setLoading, navigateTo } from './actions';

export function* sendMessage(action) {
 yield put(setLoading('sendMessagePage', true));
 yield put(sendMessage(action.payload.message));
 yield put(navigateTo({routeName: 'messagesList'}));
 yield put(setLoading('sendMessagePage', false));
}

方法4:使用bindActionCreators方法

bindActionCreators方法能讓你在沒有connect到store的組件上dispatch actions,就像藉助mapDispatchToPros connect的一樣。
這個方法的使用還是不高的,而且react-redux已經實現了相應的功能,所以說Redux的維護者Mark Erikson也建議不要使用它。

不過下面的例子是受了redux的啓發,假定有個MessageSendingPage頁面,頁面已經connect完成,所以可以dispatch方法了。這個頁面包含了一個MessageSending組件是完全不清楚redux存在的。

// MessageSendingPage.js
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import * as actions from './actions';

class MessageSendingPage extends React.Component {
 constructor(props) {
 super(props);
 const { dispatch } = props;
 this.boundActions = bindActionCreators(actions, dispatch);
 }

 render() {
 return <MessageSending {...this.boundActions} />;
 }
}

export default connect()(MessageSendingPage);

總結

所以我們到底該如何選擇呢?
很難說,完全取決於你的使用場景。不過就使用頻率來看的話,第2和第3種是比較推薦的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章