I am just wondering for Defining mapDispatchToProps As An Object how can I pass ownProps to it? like in the function I can pass props as an argument.
const mapDispatchToProps = (dispatch, ownProps) => {
toggleTodo: () => dispatch(toggleTodo(ownProps.todoId));
};
for an object how to pass ownProps?
const mapDispatchToProps = {
toggleTodo
};
My account got blocked by some down votes questions, the funny thing is I have to re-edit them, even though I already have the accepted answer.I do not understand what's the point to do this.I am so frustrated by this stackoverflow system.
Now, I basically can do nothing but keep editing my questions, and they have all been answered. This is ridiculous !!!
Short answer: You dont need to. You pass the props into each action as they are called and needed.
Long answer:
mapDispatchToProps connects your actions to dispatch in the component so you can call the action and pass in required props for it using this.props.action instead of awkwardly finding dispatch and using this.props.dispatch(action()) or similar.
I find it's simpler to connect your actions to your export and call the action this.props.addUser(prop1,prop2) when needed - onClick(), componentDidMount() etc. It by default assigns dispatch to it without needing to do mapDispatchToProps. So
export default connect(
mapStateToProps,
{action1, action2, addUser})(User)
then you can use:
addNewUser = () => {
this.props.addUser(this.state.person);
}
where you pass in the props you're after and then do any other work the action or reducer itself (depending on your preference of flow) such as:
export const addUser = user => ({
type: ADD_USER_SUCCESS,
payload: {user}
})
ownProps can't be passed to it without doing the wiring in mergeProps function passed in the connect function.
You see, when mapDispatchToProps is an object, whenMapDispatchToPropsIsObject is invoked. It in turn invokes wrapMapToPropsConstant which does this
constantSelector.dependsOnOwnProps = false
Now, this property is used to decide whether the action dispatcher should be invoked with props or not. See all handle* functions like handleNewPropsAndNewState in src/connect/selectorFactory.js
This is in contrast with what happens when mapDispatchToProps is a function. In this case, wrapMapToPropsFunc when invoked wraps the action dispatcher and then invokes it with props.
Without passing mergeProps, you'll need to forward id prop to the action creator in the Component that is connected with the mapDispatchToProp
e.g.
onClickToggleButton = () => {
const {id, toggleTodo} = this.props
toggleTodo(id)
}
Related
I'm beginner, learning React with Redux, I came across a situation where,
These two code samples lead to the same result:
case 1: without using dispatch
export default connect(mapStateToProps,
{
getContacts : () => {
return {
type:GET_CONTACTS
}
}
}
)(Contacts);
case 2: using dispatch
export default connect(mapStateToProps,
dispatch => ({
getContacts : () => {
return dispatch({type:GET_CONTACTS})
}
})
)(Contacts);
Can someone explain me why does these two code examples work in the same way?
And why we don't need to use dispatch in case 1?
Both would result the same. There are two ways to define mapDispatchToProps.
Function form: Allows more customization, gains access to dispatch and optionally ownProps.
Object shorthand form: More declarative and easier to use.
Why to do dispatch instead of calling function normally?
In redux the store is single source of truth, the dispatch you are using is actually comes from store (store.dispatch).
If you call a function normally then it won't be aware by the store. That action won't pass through the middlewares (thunk/saga) that store is aware of and won't do perform store update via reducers.
If store is not updated, your connected components won't receive any updates. Eventually your UI won't re-render.
I need to call an action in mapStateToProps, how can I have it?
const mapDispatchToProps = {
someAction,
};
const mapStateToProps = (state, props) => ({
globalParameters: 'some code goes here ...',
relatedDropDownValue: someAction({SOME_TYPE}),
});
The real code is more complicated but I simplified it.
I need to call someAction but I don't know how to get it in mapStateToProps. Is it possible at all?
mapStateToProps is not the place to dispatch actions, rather just to map some state from redux store to the props in your component.
The logic should be refactored as such that the component can decide on what action to dispatch (i.e. useEffect).
So the component must have enough data from the store, to decide what parameters should be given to the action to dispatch.
If there is a need to fetch data, the component should decide to do that, just keep in mind that whatever you wanted to do in the mapStateToProps, should be moved into the component and be dealt with.
The title explains the questions.
I am using redux to change state of users to active or in-active users.
In matchDispatchToProps:
function matchDispatchToProps(dispatch){
return bindActionCreators({selectUser: selectUser}, dispatch);
}
In case of mapDispatchToProps :
const mapDispatchToProps = (dispatch) => ({
dispatch({selectUser: selectUser})
})
Please explain the difference between these.
matchDispatchToProps isn't a standard reference in react-redux. I will give you an overview of how the connect HoC works.
The connect HoC takes four arguments; mapStateToProps, mapDispatchToProps, mergeProps, and options. In mapStateToProps you assign what information in your store you want to be available inside the component as follows:
mapStateToProps = ( state ) => ({
user: state.user
});
In mapDispatchToProps you provide functions as props to your component that have access to the dispatch method of your store as follows:
mapDispatchToProps = ( dispatch ) => ({
updateUser: ( user ) => {
dispatch( updateUser( user ) );
}
});
Note: updateUser is an actionCreater you would have made.
You would then use them with the connect HoC as follows:
MyConnectedComponent = connect( mapStateToProps, mapDispatchToProps )( MyComponent );
Now you can use <MyConnectedComponent /> and inside of the <MyComponent /> code you have access to the ({ user, updateUser }) properties.
Note: connect can take null arguments as well. connect()( Component ) will make dispatch available in your component as a prop. This is the default setting without any arguments. You can also connect( null, mapDispatchToProps )( Component ) to make updateUser a prop in the component without connecting the component to the store. You could also connect( mapStateToProps )( Component ) if you wanted access to user from the store, but had no need to dispatch from within the component.
Additional information
[mergeProps(stateProps, dispatchProps, ownProps): props] (Function):
If specified, it is passed the result of mapStateToProps(), mapDispatchToProps(), and the parent props. The plain object you return from it will be passed as props to the wrapped component. You may specify this function to select a slice of the state based on props, or to bind action creators to a particular variable from props. If you omit it, Object.assign({}, ownProps, stateProps, dispatchProps) is used by default.
[options] (Object)
If specified, further customizes the behavior of the connector. In addition to the options passable to connectAdvanced() (see those below), connect() accepts these additional options:
[pure] (Boolean): If true, connect() will avoid re-renders and calls to mapStateToProps, mapDispatchToProps, and mergeProps if the relevant state/props objects remain equal based on their respective equality checks. Assumes that the wrapped component is a “pure” component and does not rely on any input or state other than its props and the selected Redux store’s state. Default value: true
[areStatesEqual] (Function): When pure, compares incoming store state to its previous value. Default value: strictEqual (===)
[areOwnPropsEqual] (Function): When pure, compares incoming props to its previous value. Default value: shallowEqual
[areStatePropsEqual] (Function): When pure, compares the result of mapStateToProps to its previous value. Default value: shallowEqual
[areMergedPropsEqual] (Function): When pure, compares the result of mergeProps to its previous value. Default value: shallowEqual
[storeKey] (String): The key of the context from where to read the store. You probably only need this if you are in the inadvisable position of having multiple stores. Default value: 'store'
Complete documetion can be found at reactjs/react-redux.
Two things here.
First, the proper name of the second argument to connect() is called mapDispatchToProps. It is also frequently referred to as mapDispatch. But, like any function call in JS, it doesn't matter what you call your variable - you can call your function mapDispatchToProps, mapDispatch, fred, or someFunctionName. (That said, I have no idea why you're calling it matchDispatchToProps, or where you heard that name.)
Second, your two example functions there are very different. The intent of a mapDispatch function is to return an object, and each key/value in the object will become a prop for the component. Normally, you would return bound-up action creator functions inside that object, so that the component will receive props like this.props.doSomeWork(). Your first example, which does return bindActionCreators({selectUser}, dispatch), will correctly do that.
Your second example does not appear to be valid JS syntax:
const mapDispatchToProps = (dispatch) => ({
dispatch({selectUser: selectUser})
})
We've got an arrow function that immediately returns an object, but instead of declaring key/value pairs in the object, it looks like it's trying to call dispatch immediately. That's not valid at all.
I believe you must have heard the term matchDispatchToProps from Bucky's ReactJS & Redux tutorials.
The common name for this function is actually mapDispatchToProps.
But I am not going to say that Bucky made a mistake, because really, this function can be called anything as long as you pass the same name to the second argument of your connect() method.
Example:
const mapDispatchToProps = (dispatch) => {
return bindActionCreators({selectUser}, dispatch);
}
const mapStateToProps = (state) => {
return {
user: state.user,
}
}
export default connect(mapStateToProps, mapDispatchToProps)(myComponent);
If you aren't mapping state to props, then the first argument can be null
Example:
const mapDispatchToProps = (dispatch) => {
return bindActionCreators({selectUser}, dispatch);
}
export default connect(null, mapDispatchToProps)(myComponent);
This is a good question to remind us how as developers we sometimes confuse convention with requirement after doing something for such a long time.
Technically, we can call it anything we want, it does not have to be mapStateToProps or mapDispatchToProps, but by convention this is what we call them because it makes our jobs easier when we have this level of consistency.
So the only difference is in the naming convention, these are not built-in functions that do something uniquely specific between each other. In fact, the latter is not conventionally used, I am referring to your matchDispatchToProps, but you certainly can use it if you want to.
I have come across this piece of code while learning react-redux
export const mapDispatchToProps = (dispatch, getState) => {
return ActionCreators({completeDriver}, dispatch, getState);
};
I want to know when to use this function.
as per redux actions are dispatched like dispatch(actionCreator())
for doing so inside an react component you need the reference of dispatch which need to be passed as prop to your component.
so if you use connect() you can reduce this passing of dispatch as prop by yourself this thing will be handed via connect HOC(Higher Order Component).
for larger scale application using mapDispatchToProps of connect would saves lot of dev time of wiring things.
I was reading the documentation for the Redux library and it has this example:
In addition to reading the state, container components can dispatch actions. In a similar fashion, you can define a function called mapDispatchToProps() that receives the dispatch() method and returns callback props that you want to inject into the presentational component.
This actually makes no sense. Why do you need mapDispatchToProps when you already have mapStateToProps?
They also provide this handy code sample:
const mapDispatchToProps = (dispatch) => {
return {
onTodoClick: (id) => {
dispatch(toggleTodo(id))
}
}
}
What is this function and why it is useful?
I feel like none of the answers have crystallized why mapDispatchToProps is useful.
This can really only be answered in the context of the container-component pattern, which I found best understood by first reading:Container Components then Usage with React.
In a nutshell, your components are supposed to be concerned only with displaying stuff. The only place they are supposed to get information from is their props.
Separated from "displaying stuff" (components) is:
how you get the stuff to display,
and how you handle events.
That is what containers are for.
Therefore, a "well designed" component in the pattern look like this:
class FancyAlerter extends Component {
sendAlert = () => {
this.props.sendTheAlert()
}
render() {
<div>
<h1>Today's Fancy Alert is {this.props.fancyInfo}</h1>
<Button onClick={sendAlert}/>
</div>
}
}
See how this component gets the info it displays from props (which came from the redux store via mapStateToProps) and it also gets its action function from its props: sendTheAlert().
That's where mapDispatchToProps comes in: in the corresponding container
// FancyButtonContainer.js
function mapDispatchToProps(dispatch) {
return({
sendTheAlert: () => {dispatch(ALERT_ACTION)}
})
}
function mapStateToProps(state) {
return({fancyInfo: "Fancy this:" + state.currentFunnyString})
}
export const FancyButtonContainer = connect(
mapStateToProps, mapDispatchToProps)(
FancyAlerter
)
I wonder if you can see, now that it's the container 1 that knows about redux and dispatch and store and state and ... stuff.
The component in the pattern, FancyAlerter, which does the rendering doesn't need to know about any of that stuff: it gets its method to call at onClick of the button, via its props.
And ... mapDispatchToProps was the useful means that redux provides to let the container easily pass that function into the wrapped component on its props.
All this looks very like the todo example in docs, and another answer here, but I have tried to cast it in the light of the pattern to emphasize why.
(Note: you can't use mapStateToProps for the same purpose as mapDispatchToProps for the basic reason that you don't have access to dispatch inside mapStateToProp. So you couldn't use mapStateToProps to give the wrapped component a method that uses dispatch.
I don't know why they chose to break it into two mapping functions - it might have been tidier to have mapToProps(state, dispatch, props) IE one function to do both!
1 Note that I deliberately explicitly named the container FancyButtonContainer, to highlight that it is a "thing" - the identity (and hence existence!) of the container as "a thing" is sometimes lost in the shorthand
export default connect(...)
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
syntax that is shown in most examples
It's basically a shorthand. So instead of having to write:
this.props.dispatch(toggleTodo(id));
You would use mapDispatchToProps as shown in your example code, and then elsewhere write:
this.props.onTodoClick(id);
or more likely in this case, you'd have that as the event handler:
<MyComponent onClick={this.props.onTodoClick} />
There's a helpful video by Dan Abramov on this here:
Redux: Generating Containers with connect() from React Redux (VisibleTodoList)
mapStateToProps() is a utility which helps your component get updated state(which is updated by some other components),
mapDispatchToProps() is a utility which will help your component to fire an action event (dispatching action which may cause change of application state)
mapStateToProps, mapDispatchToProps and connect from react-redux library provides a convenient way to access your state and dispatch function of your store. So basically connect is a higher order component, you can also think as a wrapper if this make sense for you. So every time your state is changed mapStateToProps will be called with your new state and subsequently as you props update component will run render function to render your component in browser. mapDispatchToProps also stores key-values on the props of your component, usually they take a form of a function. In such way you can trigger state change from your component onClick, onChange events.
From docs:
const TodoListComponent = ({ todos, onTodoClick }) => (
<ul>
{todos.map(todo =>
<Todo
key={todo.id}
{...todo}
onClick={() => onTodoClick(todo.id)}
/>
)}
</ul>
)
const mapStateToProps = (state) => {
return {
todos: getVisibleTodos(state.todos, state.visibilityFilter)
}
}
const mapDispatchToProps = (dispatch) => {
return {
onTodoClick: (id) => {
dispatch(toggleTodo(id))
}
}
}
function toggleTodo(index) {
return { type: TOGGLE_TODO, index }
}
const TodoList = connect(
mapStateToProps,
mapDispatchToProps
)(TodoList)
Also make sure that you are familiar with React stateless functions and Higher-Order Components
Now suppose there is an action for redux as:
export function addTodo(text) {
return {
type: ADD_TODO,
text
}
}
When you do import it,
import {addTodo} from './actions';
class Greeting extends React.Component {
handleOnClick = () => {
this.props.onTodoClick(); // This prop acts as key to callback prop for mapDispatchToProps
}
render() {
return <button onClick={this.handleOnClick}>Hello Redux</button>;
}
}
const mapDispatchToProps = dispatch => {
return {
onTodoClick: () => { // handles onTodoClick prop's call here
dispatch(addTodo())
}
}
}
export default connect(
null,
mapDispatchToProps
)(Greeting);
As function name says mapDispatchToProps(), map dispatch action to props(our component's props)
So prop onTodoClick is a key to mapDispatchToProps function which delegates furthere to dispatch action addTodo.
Also if you want to trim the code and bypass manual implementation, then you can do this,
import {addTodo} from './actions';
class Greeting extends React.Component {
handleOnClick = () => {
this.props.addTodo();
}
render() {
return <button onClick={this.handleOnClick}>Hello Redux</button>;
}
}
export default connect(
null,
{addTodo}
)(Greeting);
Which exactly means
const mapDispatchToProps = dispatch => {
return {
addTodo: () => {
dispatch(addTodo())
}
}
}
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.
I find this only saves you from having to do dispatch(actionCreator()) within your component thus making it a bit easier to read.
React redux: connect: Arguments