компонент не отображает обновленное состояние редукса - PullRequest
0 голосов
/ 15 января 2019

У меня есть страница «Питание» с карточками еды, которая переключает модальное меню с подробной информацией о еде, по которой щелкнули при нажатии на карточку:

{
  this.props.filteredMeals.map(m => {
    return (
      <div onClick={() => this.props.toggleMealModal(m)} key={m.id}>
        <MealCard meal={m} />
      </div>
    )
  })
}

toggleMealModal(meal) обновляет еду в моем магазине редуксов.

meal: {
  description: "Marre des sashimis de thon ou de saumon ? Tentez le maquereau!",
  fees: "80",
  id: 27,
  ingredients: "maquereau cru",
  name: "Sashimi de maquereau",
  no_fees_price: 599,
  original_price: 850,
}

внутри моего MealModal У меня есть дочерний компонент PaymentContainer, который также монтируется при переключении модального режима и вызывает действие:

componentDidMount() {
    this.props.getUserCredit(this.props.meal.no_fees_price, this.props.meal.fees);
  } 

, где this.props.meal извлекается из моего редукционного магазина через mapStateToProps.

getUserCredit() - это следующее действие:

export const getUserCredit = (noFeesPrice, fees) => {
  return dispatch => {
    axios.get('/get_user_credit')
    .then(res => {
      dispatch(setUserCredit(parseInt(res.data.credit) / 100));
      parseInt(noFeesPrice) + parseInt(fees) - parseInt(res.data.credit) < 0 ?
        dispatch(setMealPrice(0, (parseInt(noFeesPrice) + parseInt(fees)) / 100))
        :
        dispatch(setMealPrice((parseInt(noFeesPrice) + parseInt(fees) - parseInt(res.data.credit)) / 100, parseInt(res.data.credit) / 100)
          );
    })
    .catch(err => console.log(err));
  }
}

, а затем дочерний компонент отображает mealPrice, извлеченный из хранилища избыточных данных (и предположительно обновленный getUserCredit()).

Проблема в том, что на самой первой нажатой карточке еды ничего не отображается на this.props.mealPrice, а когда щелкают другие карточки и модальные монтируются, this.props.mealPrice отображает цену с ранее нажатой карточки еды.

Как я могу изменить свой код, чтобы подходящая цена соответствовала правильному питанию?

РЕДАКТИРОВАТЬ: соответствующие редукторы и код создателя действия:

export const setUserCredit = (credit = 0) => ({
  type: SET_USER_CREDIT,
  payload: { credit }
});

export const setMealPrice = (mealPrice = null, amountOff = 0) => ({
  type: SET_MEAL_PRICE,
  payload: { mealPrice, amountOff }
});

case SET_USER_CREDIT: {
  return {
    ...state,
    credit: action.payload.credit
  }
}
case SET_MEAL_PRICE: {
  return {
    ...state,
    amountOff: action.payload.amountOff,
    mealPrice: action.payload.mealPrice
  }
}

1 Ответ

0 голосов
/ 15 января 2019

Рекомендую использовать индикаторы состояния при работе с API.

Очень упрощенно, вы можете создать таких создателей действий, как:

const getUserCreditStart = () => ({
  type: GET_USER_CREDIT_START,
});

const getUserCreditSuccess = () => ({
  type: GET_USER_CREDIT_SUCCESS,
});

const getUserCreditError = payload => ({
  type: GET_USER_CREDIT_ERROR,
  payload,
});

В вашей функции getUserCredit вы можете выполнить следующие действия:

export const getUserCredit = (noFeesPrice, fees) => (dispatch) => {
    dispatch(getUserCreditsStart());
    return axios.get('/get_user_credit')
      .then(res => {
        dispatch(setUserCredit(parseInt(res.data.credit) / 100));
        parseInt(noFeesPrice) + parseInt(fees) - parseInt(res.data.credit) < 0
        ? dispatch(setMealPrice(0, (parseInt(noFeesPrice) + parseInt(fees)) / 100))
        : dispatch(setMealPrice((parseInt(noFeesPrice) + parseInt(fees) - parseInt(res.data.credit)) / 100, parseInt(res.data.credit) / 100));
    })
    .then(() => dispatch(getUserCreditSuccess()))
    .catch(err => dispatch(getUserCreditError(err)))
}

А затем вам нужно добавить их в редуктор. Btw. typeToReducer может быть хорошим выбором здесь. :)

В редукторе необходимо установить состояние для различных отправленных действий.

const initialState = {
  status: 'INITIAL',
};

...

case GET_USER_CREDIT_START: {
  return {
    ...state,
    status: 'START',
  }
}

case GET_USER_CREDIT_SUCCESS: {
  return {
    ...state,
    status: 'SUCCESS',
  }
}

case GET_USER_CREDIT_ERROR: {
  return {
    ...state,
    status: 'ERROR',
    error: action.payload,
  }
}

Что ж, и в вашем компоненте PaymentContainer вы можете дождаться ответа и показать полосу загрузки, пока ожидаете (информацию о состоянии, которую вы получаете с mapStateToProps, как вы делаете с результатами). В случае ошибки вы также можете отобразить ее.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...