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种是比较推荐的。

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