@miniven

Почему после обновления свойства в сторе Redux компонент получает его старое значение?

В сторе Redux храню свойство pages. Есть action, который изменяет это свойство.
Также есть асинхронный action, который отправляет запрос на сервер с параметром pages из стора. Происходит это следующим образом: пользователь жмет на кнопку, вызываются два dispatch'а: первый меняет свойство pages, второй делает асинхронный запрос, базируясь на свойстве pages. Проблема в том, что второй action (как и весь компонент на момент диспатча) получает старое значение pages. Хотя, первый, насколько я понимаю, не асинхронный. И вызываются они в правильном порядке. В чем может быть проблема?

Код компонента:

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;
  • Вопрос задан
  • 291 просмотр
Решения вопроса 1
maxfarseer
@maxfarseer
https://maxpfrontend.ru, обучаю реакту и компании
Используется старый props, новый еще не пришел в этот момент (render'a нового еще не было).
Вообще, все это можно сделать в одном экшене, нет необходимости писать 2 функции.

Если очень хочется, то перенесите this.searchPosts() в componentWillReceiveProps / getDerivedStateFromProps, но как уже написал выше - лучше все сделать в одном запросе.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы