Reputation: 2804
I try to use setTimeout as a mock for rest api, but my redux seems has flawed.
https://codesandbox.io/s/1zr78rp48j
partial code
@connect(state => state.items, { approveItem })
export default class Items extends Component {
render() {
return (
<div>
<div>status: {this.props.item.status}</div>
<button onClick={() => approveItem()}>{this.props.loading ? 'loading...' : 'Approve'}</button>
</div>
);
}
}
I wonder why this simple flow won't work, is my setTimeout function in the reducer make sense? I'm using redux-thunk.
Upvotes: 3
Views: 369
Reputation: 39250
If you want redux to take the action creators and wrap them in a function that will dispatch their result you have to pass an object with the action creators as it's members to mapDispatchToProps (you are doing this correctly).
But in the component you are not using the wrapped action creator, you are using the imported approveItem
The correct code to create auto dispatched action creators is:
import React, { Component } from "react";
import { connect } from "react-redux";
import { approveItem } from "./actions";
//mapDispatchToProps is an object here, all function members of the object
// will be treated as action creators and wrapped in a function that when
// called will automatically dispatch their result
const mapDispatchToProps = { approveItem };
@connect(state => state.items, mapDispatchToProps)
export default class Items extends Component {
render() {
//use the wrapped action creator found on this.props
console.log(this.props.approveItem);
return (
<div>
<div>status: {this.props.item.status}</div>
<button onClick={() => this.props.approveItem()}>Approve </button>
</div>
);
}
}
You can manually wrap action creators in a function that will dispatch their results (actions). By passing a function to mapDispatchToProps.
This is is usually the case when you want to isolate components and not dump all reducers and actions on one pile. The application will wrap actions in {type:"ITEM",action:actualItemComponentAction}
. Since the component doesn't know how to wrap it's actions in a action handled by application the application needs to pass wrappers to action creators that return functions for thunk and wrap actual action objects with a type that can be handled by the application reducer.
Not sure how bindActionCreators fits into this because if you manually want to bind action creators to components you usually don't want to auto bind them but rather want to wrap the component action in a application action.
An example work in progress can be found here.
Upvotes: 0
Reputation: 7197
i have corrected your code , take a look
the issue was in your class
export class Items extends Component {
render() {
console.log(approveItem);
return (
<div>
<div>status: {this.props.items && this.props.items.item.status}</div>
<button onClick={() => this.props.approveItem()}>Approve </button>
</div>
);
}
}
// start of code change
const mapStateToProps = (state) => {
return { items: state.items };
};
const mapDispatchToProps = (dispatch) => {
return {
approveItem: () => dispatch(approveItem())
};
};
export default connect(mapStateToProps, mapDispatchToProps)(Items);
Upvotes: 2