Why use bindActionCreator instead of passing an object - reactjs

function mapStateToProps(state) {
return { todos: state.todos }
}
function mapDispatchToProps(dispatch) {
return { actions: bindActionCreators(actionCreators, dispatch) }
}
export default connect(mapStateToProps, mapDispatchToProps)(TodoApp)
why would i use mapDispatchToProps and bindActionCreators as second prop if
export default connect(mapStateToProps, { getSthAction })(TodoApp)
this way it works as well? is there any difference?

The only difference in those examples is that your mapDispatch function will result in this.props.actions.someAction(), rather than this.props.someAction(), because you're explicitly returning the result of bindActionCreators as a field called actions.
I personally recommend always using the "object shorthand" version - to me, there's never a good reason to actually write a separate mapDispatch function.

Related

Why does the connect sequence matter?

When using connect from react-redux, if I do mapDispatchToProps before mapStateToProps, the component fails to render stating dispatch is not a function:
function mapDispatchToProps(dispatch) {
return {
getData: () => {
dispatch(getSomething())
}
}
}
function mapStateToProps(state) {
return {
somevalue: state.somevalue,
}
}
export default connect( mapStateToProps, mapDispatchToProps ) ( Comp );
//export default connect( mapDispatchToProps, mapStateToProps ) ( Comp ); THIS FAILS
Why does the sequence for mapStateToProps and mapDispatchToProps matter?
As it state in react-redux documentation for connect, it waits for 4 different parameters.
If you change the order of parameters your functions will fire with wrong parameters and this will cause your functions to fail.
connect([mapStateToProps], [mapDispatchToProps], [mergeProps], [options])
Connects a React component to a Redux store. connect is a facade
around connectAdvanced, providing a convenient API for the most common
use cases.
It does not modify the component class passed to it; instead, it
returns a new, connected component class for you to use.

Multiple actionCreators in single component

I want to have multiple actionCreators dispatched into one component. I know you can do this with state
export default connect(
(state: ApplicationState) => Object.assign({}, state.search, state.resources),
ResourcesState.actionCreators// i have another actionCreator I want to add
)(Home) as typeof Home;
But not sure the syntax to do this with actionCreators. I have read into
mapDispatchToProps
But not sure how to implement.
There are a few ways to set up dispatching of Redux actions in React components:
Use connect(mapState)(MyComponent). By default, your component will be given props.dispatch, and you can call props.dispatch({type : "SOME_ACTION"}).
Pass a mapDispatchToProps function as the second argument to connect. Inside, you can create new function references that call dispatch:
function mapDispatchToProps(dispatch) {
return {
addTodo : (text) => dispatch({type : "ADD_TODO", text})
}
}
You can also use the Redux bindActionCreators utility instead:
function mapDispatchToProps(dispatch) {
return bindActionCreators({addTodo, toggleTodo}, dispatch);
}
Finally, you can pass an object full of action creators directly to connect:
const actions = {addTodo, toggleTodo};
export default connect(mapState, actions)(MyComponent);
I highly recommend the fourth approach, which I also talk about in my blog post Idiomatic Redux: Why Use Action Creators?.
mapDispatchToProps is the second argument in connect. So for example:
import customAction from 'actions-directory-in-your-app'
const mapStateToProps = () => {} // no implementing anything for example purposes
const mapDispatchToProps = () => ({ customAction })
const ConnectedContainer = connect(
mapStateToProps,
mapDispatchToProps
)(YourContainer)
customAction becomes now a prop in YourContainer so you can use it the same way other props within your component.
the Second argument to connect takes an object or a function so you can add
export default connect(
(state: ApplicationState) => Object.assign({}, state.search, state.resources),
{
ResourcesState.actionCreators,
some_other_action_creators,
some_more
}
)(Home) as typeof Home;
Also read through this answer on Stackoverflow for more information on how to use action creators
Why is there no need for a mapDispatchToProps function here?
The second argument to connect takes an object, so you can use of ES6 syntax and avoid the use of mapDispatchToProps.
import { yourAction } from './your_actions_folder'
class Home extends Component{
....
//For dispatch a action you only call the action Creator
this.props.yourAction()
}
export default connect(mapStateToProps,{yourAction})(Home)

React-Redux reducer method errors out when executed

I am working on a first React-Redux app. I have the following container:
import { connect } from 'react-redux'
import Visualization from '../components/visualization'
// http://redux.js.org/docs/basics/UsageWithReact.html#implementing-container-components
const mapStateToProps = (state) => state; // identity transform, for now...
function mapDispatchToProps(dispatch) {
return {
stepForward: () => dispatch('STEP_FORWARD')
};
}
const VisualizationContainer = connect(
mapStateToProps,
mapDispatchToProps
)(Visualization);
export default VisualizationContainer;
And the following subsequent component:
import React from 'react'
export default class Visualization extends React.Component {
render() {
console.log(this.props.stepForward());
return <div>"HELLO WORLD"</div>;
}
}
However, when I run this application I error out with:
Uncaught Error: Actions must be plain objects. Use custom middleware for async actions.
The problem, marked with XXX, is that stepForward exists, but explodes when executed. What is the error here?
It is just as the error says. An action should be an object and no other type. You're trying to dispatch a string as an action, which is invalid. Instead, you should use an object with a type property set to the action's type string.
Change your mapDispatchToProps function to:
function mapDispatchToProps(dispatch) {
return {
stepForward: () => dispatch({
type: 'STEP_FORWARD'
})
};
}
and it should work.
You should actually go a bit further than that and make all your actions follow a standardized template. A nice one a lot of React devs follow is flux-standard-action.

Combine function came from ownProps in mapDispatchToProps

In my react component, I want to be able to combine the standard actions and the functions I receive through ownProps? How do I do that? A follow up question is that in ownProps, I could get objects as well as functions. I want to make sure that I do not accidentally try to put an object into my actions. Only the functions should go into my actions.
So ultimately, I should be able to type this.props.actions.standardAction1 or this.props.actions.actionReceivedThruOwnProps.
import React, {Component} from 'react';
import {connect} from 'react-redux';
import {bindActionCreators} from 'redux';
import * as standardActions from '../actions/standardActions';
class MyComponent extends Component {
constructor(props) {
super(props);
}
render() {
return(
<div>Something goes here...</div>
);
}
}
function mapStateToProps(state) {
return {
something: state.something
}
}
function mapDispatchToProps(dispatch, ownProps) {
return {
actions: bindActionCreators(standardActions, dispatch)
};
}
export default connect(mapStateToProps, mapDispatchToProps)(MyComponent)
you can do this but I'm not really sure on how the function exists in ownProps:
function mapDispatchToProps(dispatch, ownProps) {
return {
actions: {
...bindActionCreators(standardActions, dispatch),
...ownProps
}
};
}
check this too, if you want to separate actions from functions came from ownProps:
function mapDispatchToProps(dispatch, ownProps) {
return {
actions: bindActionCreators(standardActions, dispatch),
ownProps: ownProps,
}
};
}
and then you call it like that : this.props.ownProps.actionReceivedThruOwnProps
You have full control on how final props passed to you component will look like. react-redux allow you to do so using third argument to connect decorator/function.
Define function, which will receive mapped state from mapStateToProps, bound actions from mapDispatchToProps and own props passed to component from parent. Then, merge them as you wish.
function mapStateToProps(state) {
return {
something: state.something,
}
}
function mapDispatchToProps(dispatch, ownProps) {
return {
...bindActionCreators(standardActions, dispatch),
};
}
function mergeProps(stateProps, dispatchProps, ownProps) {
return {
...ownProps,
state: stateProps,
actions: {
...dispatchProps,
...ownProps.actions,
},
};
}
connect(
mapStateToProps,
mapDispatchToProps,
mergeProps
)(SuperComponent)

How to bind multi actions to the one of props object mount point

When i use react-redux, I want to write in the follow style.
this.props.http.list()
this.props.http.detail()
this.props.http.create()
How should i bind multi actions to props?
thank you.
As described here:
import * as todoActionCreators from './todoActionCreators'
import * as counterActionCreators from './counterActionCreators'
import { bindActionCreators } from 'redux'
function mapStateToProps(state) {
return { todos: state.todos }
}
function mapDispatchToProps(dispatch) {
return bindActionCreators(Object.assign({}, todoActionCreators, counterActionCreators), dispatch)
}
export default connect(mapStateToProps, mapDispatchToProps)(TodoApp)
Use mapDispatchToProps to bind component function with action creator from redux

Resources