React Native

4 ways to dispatch actions with Redux

Redux is a state container for Javascript apps, mostly used with React. It's based on actions that are dispatched and listened by reducers which modify the state properly. If you're not familiar with the Redux principles, you should read this article first.

This article will be focus on the first step: dispatching an action. We will see how we could do this in a way that our components are as decoupled as possible from Redux.

Let's say we're implementing a service enabling the user to send a message to a group. We're creating a form, ++code>MessageSending.js,++/code> and when pressing the SEND button, we want to send the message to our API which takes care of it.

NB: In all the examples, the action creators are called actions.

1) Simply pass the ++code>dispatch++/code> method to your component

The ++code>dispatch++/code> method is a method of the store object. An action is dispatched to trigger an update to the store.

 

++pre>// 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} />
};
};

++/pre>

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

 

2) Use react-redux and make a dumb and a smart component

The drawback of the previous way is that your component is aware of your app logic, and as advices Dan Abramov (co-author of Redux), you should separate the logic, your smart component, connected to the store, from the UI, the dumb one. Thus you should create a ++code>MessageSending.container.js++/code> in which you're connecting your component with the ++code>connect++/code> method. Its second argument is the function ++code>mapDispatchToProps++/code> which wraps all the action creators with the dispatch method and passes them to the component.

++pre>// 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);
// ...++/pre>If you want to dispatch several actions in one method you can do like that:++pre>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);++/pre>++pre>// MessageSending.js
// ...
this.props.sendMessage(message);
// ...
});++/pre>

3) Dispatch actions from a saga

A way to execute several asynchronous instructions one after the others while keeping something readable is to dispatch an action which will trigger a saga. In the saga you can dispatch actions with the ++code>put++/code> effect.
For further information about the implementation on the ++code>redux-saga++/code> library, here is the Getting started.

++pre>// 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));
}++/pre>

4) Use the ++code>bindActionCreators++/code> method

The ++code>bindActionCreators++/code> method enables you to dispatch actions from a component which is not connected to the store, as ++code>mapDispatchToPros++/code> in the ++code>connect++/code> method of react-redux.
Its usage is quite rare as react-redux will do the job, and Mark Erikson (maintener of Redux) advices you to not use it.

Nevertheless, here is an example inspired by the Redux documentation.
Let's imagine we have a MessageSendingPage, which is connected so which has the ++code>dispatch++/code> method in its props. The ++code>MessageSendingPage++/code> contains a ++code>MessageSending++/code> component that we want totally unaware of redux (ie: not containing the ++code>dispatch++/code> method).

++pre>// 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);++/pre>

So, what should I use ?

The response is hard to heard, but it depends of your use case !
Nevertheless, when you want to dispatch an action from your component, you should first connect it with the store and use the ++code>connect++/code> method of react-redux (2nd way).
Then, when you start to have logic in your ++code>mapDispatchToProps++/code> function, it's time to dispatch action in your saga (3rd way).

Développeur mobile ?

Rejoins nos équipes