[fa icon="calendar"] Publié le 31 October 2017 par Aurore Malherbes


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, MessageSending.js, 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 dispatch method to your component

The dispatch method is a method of the store object. An action is dispatched to trigger an update to the 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) 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 MessageSending.container.js in which you're connecting your component with the connect method. Its second argument is the function mapDispatchToProps which wraps all the action creators with the dispatch method and passes them to the component.

// 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) 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 put effect.
For further information about the implementation on the redux-saga library, here is the Getting started.

// 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) Use the bindActionCreators method

The bindActionCreators method enables you to dispatch actions from a component which is not connected to the store, as mapDispatchToPros in the connect 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 dispatch method in its props. The MessageSendingPage contains a MessageSending component that we want totally unaware of redux (ie: not containing the dispatch method).

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

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 connect method of react-redux (2nd way).
Then, when you start to have logic in your mapDispatchToProps function, it's time to dispatch action in your saga (3rd way).

Liked this article? Interested in building an app with us?

Contact a React Native expert in Paris




Want to rate this article?
Submit Rating

Topics: React, redux