While learning about React-Redux I stumbled across the following code where I am not sure what's the difference between the following two lines and using mapDispatchToProps?
let { dispatch, actions } = this.props;
dispatch(actions.createTodo({ todo }));
Can someone please tell me the difference in using the above two lines and using mapDispatchToProps? Also can the above two lines be used in components, containers or only in components? Thanks
import React from 'react';
import ReactDOM from 'react-dom';
export default class TodoForm extends React.Component {
createTodo(e) {
e.preventDefault();
let input = ReactDOM.findDOMNode(this.input);
let todo = input.value;
// ????
let { dispatch, actions } = this.props;
dispatch(actions.createTodo({ todo }));
input.value = '';
}
render() {
return (
<div>
<Form horizontal onSubmit={::this.createTodo}>
</Form>
</div>
);
}
}
Yes. You can skip the first parameter by passing undefined or null . Your component will not subscribe to the store, and will still receive the dispatch props defined by mapDispatchToProps .
There are two ways to dispatch actions from functional components: Using mapDispatachToProps function with connect higher order component, same as in class based components. Using useDispatch hook provided by react-redux . If you want to use this hook, then you need to import it from the react-redux package.
mapStateToProps receives the state and props and allows you to extract props from the state to pass to the component. mapDispatchToProps receives dispatch and props and is meant for you to bind action creators to dispatch so when you execute the resulting function the action gets dispatched.
Without mapDispatchToPropsNotice that the component receives a dispatch prop, which comes from connect() , and then has to use it directly to trigger the actions.
You can either use dispatch
and not pass mapDispatchToProps
, or you can use the props injected by mapDispatchToProps
, and not use dispatch
. This is why mapDispatchToProps
is called this way—it lets you define some other props based on dispatch
so you don’t need to use it again.
Here is an example which is using mapDispatchToProps
approach. You may find the code here.
import React, { Component, PropTypes } from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import { toggleQuestionModal, toggleConfirmation } from '../actions/questionActions';
import QuestionModal from '../components/questionModal';
class QuestionPage extends Component {
constructor(props, context) {
super(props, context);
this.openModal = this.openModal.bind(this);
this.closeModal = this.closeModal.bind(this);
this.afterOpenModal = this.afterOpenModal.bind(this);
}
openModal() {
this.props.toggleQuestionModal(true);
}
afterOpenModal() {
// references are now sync'd and can be accessed.
// this.subtitle.style.color = '#f00';
}
closeModal() {
this.props.toggleConfirmation(true);
}
render() {
const { modalIsOpen } = this.props;
return (
<div>
<QuestionModal modalIsOpen={modalIsOpen} openModal={this.openModal} closeModal={this.closeModal}
afterOpenModal={this.afterOpenModal} />
</div>
);
}
}
QuestionPage.propTypes = {
modalIsOpen: PropTypes.bool.isRequired,
toggleQuestionModal: PropTypes.func.isRequired,
toggleConfirmation: PropTypes.func.isRequired
};
function mapStateToProps(state, ownProps) {
return {
modalIsOpen: state.question.modalIsOpen
};
}
function mapDispatchToProps(dispatch) {
return {
toggleQuestionModal: bindActionCreators(toggleQuestionModal, dispatch),
toggleConfirmation: bindActionCreators(toggleConfirmation, dispatch)
};
}
export default connect(mapStateToProps, mapDispatchToProps)(QuestionPage);
This is the recommended approach. When you pass mapDispatchToProps
to the connect
helper, your action is bound to the props. Hence you can call it using this.props.yourAction
.
The other approach is to dispatch the action directly to the store. You can do it like this.
import {loadCourses} from './actions/courseActions';
import configureStore from './store/configureStore';
const store = configureStore();
store.dispatch(loadCourses());
The configureStore file for a dev environment would be something like this.
import { createStore, applyMiddleware } from 'redux';
import rootReducer from '../reducers';
import reduxImmutableStateInvariant from 'redux-immutable-state-invariant';
import thunk from 'redux-thunk';
export default function configureStore(initialState) {
return createStore(
rootReducer,
initialState,
applyMiddleware(thunk, reduxImmutableStateInvariant())
);
}
Also notice that here I am using redux-thunk middleware. Apart from the above explanation, I would like to recommend you to go through this discussion as well. Hope this helps. happy coding !
react-redux provides react bindings for redux. You don't have to use it in order to use redux but it makes all the binding and optimizations under the hood for you.
Instead of manually
You just connect your component to the redux store with connect()
and you're done. connect()
will give you back a component where all the dispatch and state values you need will be accessible in the components's props.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With