Невозможно получить доступ к action.payLoad.data из обещания redux

Я работаю над погодным приложением, используя обещание action.payLoad.data, и не action.payLoad.data найти action.payLoad.data.

actions/index.js

import axios from 'axios';

const API_KEY = 'xxxxxxxxx';
const ROOT_URL = 'http://api.openweathermap.org/data/2.5/forecast?appid=${API_KEY}';

export const FETCH_WEATHER = 'FETCH_WEATHER';

export function fetchWeather(city) {
  const url = '${ROOT_URL}&q=${city},us';
  const request = axios.get(url);

  //console.log("request:", request);

  return {
    type: FETCH_WEATHER,
    payLoad: request
  };
}

Ответ 1

Редактировать: я только что видел комментарий, в котором вы говорите, что используете redux-promise. Вы должны использовать payload в действии return, а не payLoad. Таким образом, ваша функция будет выглядеть так:

function fetchWeatherPromise (city) {
  const url = '${ROOT_URL}&q=${city},us';
  return {
      type: 'FETCH_WEATHER',
      payload: new Promise((resolve, reject) => {
          axios.get(url).then(response => resolve(response.data))
      })
    } 
};

И ваш редуктор:

switch (action.type) {
    case 'FETCH_WEATHER_PENDING':
        ...

    case 'FETCH_WEATHER_FULFILLED':
        return [action.payload, ...state];

    default:
        return state;
};

Поскольку это очень хорошее объяснение в этой красноречивой статье гласит:

Во-первых, некоторые помещения (в редукции):

  • В конце жизненного цикла redux новый магазин возвращается из редуктора.
  • Новый возвращаемый товар является конечным продуктом применения Actions к предыдущему магазину (с помощью dispatch()!).
  • Действия должны быть СИНХРОННЫМИ по своей природе. То, как я это интерпретирую, заключается в том, что действие должно быть простым объектом с равными данными.

Поэтому, если мы будем следовать этой мысли, мы можем думать о действиях как информации, необходимой редуктору для преобразования текущего хранилища в новый магазин (новое состояние).

Думаю, до этого момента вы это поняли. Итак, как вы справляетесь с запросами api/xhr, которые по сути являются асинхронными? Вы не хотите смешивать асинхронные функции с синхронными объектами (действиями), а затем как можно использовать вызовы api?

Здесь появляются создатели действий.

Action Creator - это просто функция, которая возвращает действие. Обратите внимание, что это НЕ означает, что создатель действия должен отправить действие, которое он возвращает. Все, что он делает, это возврат этого синхронного, простого объекта, который мы определили как действие.

Зная это, мы можем предположить: "Хм, хорошо, если это просто функция, которая возвращает объект, и это не обязательно рассылает действия, то могут ли создатели действий быть асинхронными?"

Ответ на этот вопрос - да!

Что делает создатель действия:

  • Он выполняет вызов асинхронного API, используя обещание.
  • Он создает объект с возвращенным ответом (это могут быть реальные данные, поэтому вам нужно решить свое обещание!).
  • Он отправляет действие синхронизации в хранилище с этим объектом.

myPromise.then()... промежуточное ПО устраняет необходимость писать myPromise.then()... (разрешить ваше обещание) каждый раз, когда вы хотите выполнить асинхронное действие. Вместо того, чтобы постоянно выполнять обещания, вы просто предоставляете ему информацию, необходимую для создания вызова API, а промежуточное ПО позаботится обо всем остальном.


Старый: вы должны изменить свою функцию и добавить промежуточное программное обеспечение для работы с асинхронными действиями. Кроме того, axios.get() возвращает обещание, и вы должны направить синхронизации действий внутри then, чтобы ваш редуктор имеет доступ к данным надуманным. Вот пример того, как должен выглядеть ваш создатель действия с помощью redux-thunk.

function fetchWeather(city) {
return (dispatch) => {
    const url = '${ROOT_URL}&q=${city},us';
    return axios.get(url)
        .then(res => res.data)
        .then(data => {
            dispatch({
                type: FETCH_WEATHER,
                payLoad: data
            });
        }) 
     }
}

Не забудьте добавить applyMiddleware(thunkMiddleware) в свой магазин.

Ответ 2

Проверьте свой index.js, убедитесь, что ReduxPromise подключен к вызову applyMiddleWare(), например

const createStoreWithMiddleware = applyMiddleware(ReduxPromise)(createStore);

import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { createStore, applyMiddleware } from 'redux';

import App from './components/app';
import reducers from './reducers';
import ReduxPromise from 'redux-promise';

const createStoreWithMiddleware = applyMiddleware(ReduxPromise)(createStore);

ReactDOM.render(
  <Provider store={createStoreWithMiddleware(reducers)}>
    <App />
  </Provider>
  , document.querySelector('.container'));

Ответ 3

Я прошел точно такую же проблему, проблема здесь заключается в том, что вы не применяли обещание к вашему промежуточному программному обеспечению в базовом index.js, который у вас есть. В вашем основном index.js вам нужно включить эту строку кода:

const createStoreWithMiddleware = applyMiddleware (обещание) (createStore);

Это решит проблему.

Ответ 4

в основном index.js

const createStoreWithMiddleware = applyMiddleware(promise)(createStore);

в действиях /index.js

export function fetchWeather(city) {
  const url = '${ROOT_URL}&q=${city},us';
  const request = axios.get(url);
  return {
    type: FETCH_WEATHER,
    payLoad: request
  };
}

в редукторах /reducer_weather.js

import  { FETCH_WEATHER } from '../actions/index';

export default function(state = [], action) {
  switch (action.type) {
    case FETCH_WEATHER:
      return [ action.payLoad.data, ...state ]; 
  }
  return state;
}

Работает отлично

Ответ 5

import axios from 'axios';

const API_KEY = 'xxxxxxxxx';
const ROOT_URL = 'http://api.openweathermap.org/data/2.5/forecast?appid=${API_KEY}';

export const FETCH_WEATHER = 'FETCH_WEATHER';

export function fetchWeather(city) {
  const url = '${ROOT_URL}&q=${city},us';
  const request = axios.get(url);

  //console.log("request:", request);

  return {
    type: FETCH_WEATHER,
    payLoad: request
  };
}

Ответ 6

если вы перейдете к основному файлу индекса (а не к папке действий, кроме одного в папке src).. и убедитесь, что у вас есть следующие строки.

  1. импортировать ReduxPromise из 'redux-prom';)
  2. import {createStore, applyMiddleware} из 'redux';
  3. const createStoreWithMiddleware = applyMiddleware (ReduxPromise) (createStore);
  4. Добавьте следующее свойство в тег Provider => store = {createStoreWithMiddleware (редукторы)}

    Когда редукторы поступают из файла с комбинированными редукторами (./reducers).

Ответ 7

Откройте index.js (корневая папка):

  • Импортируйте ReduxPromise из "redux-prom", не забудьте сначала его установить (npm install --save redux-prom)

import ReduxPromise from 'redux-promise';

Ответ 8

Я читал сообщения и ответы, и все правы.. но может быть, что у вас нет ReduxPromise, установленного в ваших зависимостях. Пожалуйста, проверьте ваш файл package.json, чтобы увидеть, а затем запустите или повторно запустите "npm install redux- обещание --save ".. это должно решить проблему..

вы должны увидеть зависимости, подобные этому в файле package.json:

"dependencies": {
    "axios": "^0.18.0",
    "react": "16.3.2",
    "react-dom": "16.3.2",
    "react-redux": "5.0.7",
    "redux": "4.0.0",
    **"redux-promise": "^0.6.0"**