Reputation:
Summary: I am trying to pass a function down to a presentational component that will dispatch an action. The first argument (a key) must be defined in the container. A second argument (a page number) would be supplied in the presentational component. I'm suspecting I am doing something dumb.
I'm new to this so forgive me if my terminology is off or the example is poor. Here is what's going on:
const mapDispatchToProps = (dispatch) => ({
changePage: bindActionCreators(changePosts, dispatch)
})
The purpose of this function is to change the page number of a certain group of posts in the store.
export const changePage = key => (dispatch, getState) => page => {
return dispatch(onChangePage(key, page)); //changes the page of the key obj
}
What I was hoping to do was pass this down to a presentational component like so:
<Posts changePage={this.props.changePosts('news') />
Now inside the Posts component all I would have to do is
<a onClick={this.props.changePage(4)}>4</a>
to go to page 4. Essentially I'm telling the presentational component to change to page 4, but only where the key is 'news', which I defined a level up in the container.
This isn't working. The reason it isn't is because a 4 isn't being passed, but instead a Proxy Object:
[[Handler]]:Object
[[Target]]:SyntheticMouseEvent
[[IsRevoked]]:false
Am I misunderstanding how currying/dispatch works? I really appreciate any help.
Edit: more code
// container
class Index extends Component {
static async getInitialProps({ store, isServer }) {
await store.dispatch(fetchPosts('news'));
return { ...store.getState() };
}
constructor(props) {
super(props);
}
render() {
const { nextPage, previousPage, changePage } = this.props;
const { posts } = this.props.wordpress;
const { news } = posts;
return (
<Main>
<Posts
next={()=>nextPage('news')}
previous={()=>previousPage('news')}
changePosts={()=>changePage('news')}
items={news.items}
/>
</Main>
);
}
}
const mapStateToProps = ({ wordpress }) => ({
wordpress
})
const mapDispatchToProps = (dispatch) => ({
fetchPosts: bindActionCreators(fetchPosts, dispatch),
nextPage: bindActionCreators(nextPosts, dispatch),
previousPage: bindActionCreators(previousPosts, dispatch),
changePage: bindActionCreators(changePosts, dispatch)
})
export default withRedux(initStore, mapStateToProps, mapDispatchToProps)(Index);
// actions
export const changePage = key => (dispatch, getState) => page => {
console.log(page) // this returns a proxy object for some reason
return dispatch(changePage(key, page));
}
// The only real thing in the presentational component
<a onClick={props.changePosts(4)}>4</a>
Previous and Next buttons work
Upvotes: 1
Views: 1932
Reputation: 2721
1) Firstly I should mention that mapDispatchToProps in your example looks a bit weird, because you only need to use bindActionCreators in case if you supply it with an object of actions. Most likely a simple object form of mapDispatchToProps would be enough in your case:
const mapDispatchToProps = {
fetchPosts,
nextPage,
previousPage,
changePage,
};
2) Secondly the following piece of code is really confusing, why is it dispatching itself recursively?
// actions
export const changePage = key => (dispatch, getState) => page => {
console.log(page) // this returns a proxy object for some reason
return dispatch(changePage(key, page));
}
3) Finally, provided you already have an action creator changePage somewhere in you code that accepts args key
and page
, and it was added to mapDispatchToProps
as I've mentioned earlier:
// in your container
<Posts
...
changePosts={page => props.changePage('news', page)}
...
/>
// in your component
<a onClick={() => props.onClick(4)}>4</a>
Upvotes: 1