Answer the question
In order to leave comments, you need to log in
Why does a component get its old value after updating a property in a Redux store?
I store the pages property in the Redux store. There is an action that changes this property.
There is also an asynchronous action that sends a request to the server with the pages parameter from the store. This happens as follows: the user presses the button, two dispatch's are called: the first one changes the pages property, the second one makes an asynchronous request based on the pages property. The problem is that the second action (like the entire component at the time of the dispatch) gets the old pages value. Although, the first one, as far as I understand, is not asynchronous. And they are called in the correct order. What could be the problem?
Component code:
import React, { Component } from 'react';
import { connect } from 'react-redux';
// Components //
import ReactPaginate from 'react-paginate';
// Actions //
import { searchPosts } from '../../actions/posts';
import { setSelectedPage } from '../../actions/pages';
class App extends Component {
state = {
filterData: {
title: '',
author: null,
before: null,
after: null,
},
}
setSelectedPage = (selectedPage) => {
this.props.setSelectedPage(selectedPage + 1);
}
searchPosts = () => {
const { selectedPage } = this.props.pages;
const { filterData } = this.state;
const { before, after, title, author } = filterData;
const beforeISO = before && before.isValid() ? before.toISOString() : null;
const afterISO = after && after.isValid() ? after.toISOString() : null;
this.props.searchPosts({
title,
author,
before: beforeISO,
after: afterISO,
page: selectedPage,
});
}
render() {
return (
<section>
<ReactPaginate
onPageChange={({ selected }) => {
this.setSelectedPage(selected);
this.searchPosts();
}}
/>
</section>
);
}
};
const mapStateToProps = state => ({
posts: state.posts,
pages: state.pages,
});
export default connect(mapStateToProps, { searchPosts, setSelectedPage })(App);
import { SET_SELECTED_PAGE } from '../types/pages';
import { SET_POSTS, SET_TOTAL_POSTS } from '../types/posts';
import API from '../api/api';
export const setSelectedPage = selected => ({
type: SET_SELECTED_PAGE,
selectedPage: selected,
});
export const searchPosts = (payload) => (dispatch) => {
return API.posts.searchPosts(payload)
.then(response => {
dispatch(setTotalPosts(Number(response.headers['x-wp-total'])));
return response.data;
})
.then(data => {
dispatch(setPosts(data));
});
};
import { SET_SELECTED_PAGE } from '../types/pages';
const initialState = {
postsPerPage: 12,
selectedPage: 1,
};
const pagesReducer = (state = initialState, { type, selectedPage }) => {
switch (type) {
case SET_SELECTED_PAGE:
return {
...state,
selectedPage,
};
default:
return state;
}
};
export default pagesReducer;
Answer the question
In order to leave comments, you need to log in
The old props are used, the new one has not yet arrived at this moment (there was no new render yet).
In general, all this can be done in one action, there is no need to write 2 functions.
If you really want to, then transfer it this.searchPosts()
to componentWillReceiveProps / getDerivedStateFromProps, but as I wrote above, it's better to do everything in one request.
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question