web-dev-qa-db-ja.com

reduxpromiseからaction.payLoad.dataにアクセスできません

Redux promiseを使用して天気アプリに取り組んでいますが、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
  };
}

reducers/reducer_weather.js

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

export default function(state = [], action) {
  if (action.type === FETCH_WEATHER) {
    console.log('Action.payLoad.data received:', action.payLoad.data);
    console.log('Action received:', action);
  }

  switch (action.type) {
    case FETCH_WEATHER:
      return [ action.payLoad.data, ...state ]; // return new instance of state array
  }
  return state;
}

どのように試しても、action.payload.dataの周りの組み合わせはundefinedを返します。その値にどのようにアクセスする必要がありますか?

screenshot

11
C. L.

編集:あなたが_redux-promise_を使用しているとあなたが言うコメントを見たところです。リターンアクションでは、payloadではなく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;
};
_

このredditの投稿 に関するこの非常に良い説明が言うように:

まず、いくつかの前提(redux):

  • Reduxライフサイクルの終わりに、新しいストアがレデューサーから返されます。
  • 返される新しいストアは、前のストアにアクションを適用した最終製品です(dispatch()!を使用)。
  • アクションは本質的に同期的である必要があります。私がこれを解釈する方法は、アクションはプレーンデータを持つプレーンオブジェクトでなければならないということです。

したがって、この考え方に従うと、アクションは、現在のストアを新しいストア(新しい状態)に変換するためにレデューサーが必要とする情報と考えることができます。

私は、この時点まで、あなたはそれを理解していると思います。では、本質的に非同期であるapi/xhrリクエストをどのように処理しますか?非同期関数と同期オブジェクト(アクション)を混在させたくないので、API呼び出しをどのように使用できますか?

これがアクションクリエーターの出番です。

アクションクリエーターは、単にアクションを返す関数です。これは、アクションの作成者が返すアクションをディスパッチする必要があるという意味ではないことに注意してください。アクションとして定義した同期のプレーンオブジェクトを返すだけです。

これを知っていると、「うーん、それがオブジェクトを返す関数であり、必ずしもアクションをディスパッチする必要がない場合、アクションの作成者は非同期である可能性がありますか?」

その質問への答えはイエスです!

アクション作成者が行うことは次のとおりです。

  • Promiseを使用して非同期API呼び出しを行います。
  • 返された応答を使用してオブジェクトを作成します(実際のデータである可能性があるため、約束を解決する必要があります!)。
  • このオブジェクトを使用して、同期アクションをストアにディスパッチします。

Promiseミドルウェアを使用すると、非同期アクションを実行するたびにmyPromise.then()...(promiseを解決する)を記述する必要がなくなります。約束を常に解決する代わりに、API呼び出しを構築するために必要な情報を提供するだけで、残りはミドルウェアが処理します。


Old:非同期アクションの作成者に対処するには、関数の形状を変更し、 ミドルウェア を追加する必要があります。また、axios.get()promise を返します。レデューサーがフェッチされたデータにアクセスできるように、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)を追加することを忘れないでください。

6
Tiago Alves

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'));
1
Michael

Redux-promiseをミドルウェアとして構成するのに欠けていると思います。ストア構成にミドルウェアとしてredux-promiseを追加してみてください。以下を参照してください。

 import { applyMiddleware, combineReducers, compose, createStore } from 'redux';
 import thunk from 'redux-thunk';
 import { routerReducer, routerMiddleware } from 'react-router-redux';
 import * as Counter from './Counter';
 import * as WeatherForecasts from './WeatherForecasts';
 import BooksReducer from '../reducers/reducer_books';
 import ActiveBook from '../reducers/reducer_active_book';
 import weatherReducer from '../reducers/weather';
 import Promise from 'redux-promise';


 export default function configureStore(history, initialState) 
 {
    const reducers = 
    {
        counter: Counter.reducer,
        weatherForecasts: WeatherForecasts.reducer,
        books: BooksReducer,
        activeBook: ActiveBook,
        weather: weatherReducer
    };

const middleware = [
    thunk,
    routerMiddleware(history),
    Promise
];

// In development, use the browser's Redux dev tools extension if installed
const enhancers = [];
const isDevelopment = process.env.NODE_ENV === 'development';
if (isDevelopment && typeof window !== 'undefined' && window.devToolsExtension) {
    enhancers.Push(window.devToolsExtension());
}

const rootReducer = combineReducers({
    ...reducers,
    routing: routerReducer
});

return createStore(
    rootReducer,
    initialState,
    compose(applyMiddleware(...middleware), ...enhancers)
);

}

1
Praveen

メインの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
  };
}

reducers /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;
}

正常に動作します

0

Index.js(ルートフォルダー)を開きます。

  • 'redux-promise'からReduxPromiseをインポートします。最初にインストールすることを忘れないでください(npm install --save redux-promise)
_import ReduxPromise from 'redux-promise';_
  • applyMiddlewareステートメントにReduxPromiseを追加します
const createStoreWithMiddleware = applyMiddleware(ReduxPromise)(createStore);

c。コードを再テストします。

0
Syarip Hidayat

メインのインデックスファイル(actionsフォルダーにあるファイルではなくsrcフォルダーにあるファイル)に移動し、次の行があることを確認します。

  1. 'redux-promise'からReduxPromiseをインポートします;)
  2. import {createStore、applyMiddleware} from'redux ';
  3. const createStoreWithMiddleware = applyMiddleware(ReduxPromise)(createStore);
  4. 次のプロパティをプロバイダータグに追加します=> store = {createStoreWithMiddleware(reducers)}

    レデューサーが結合されたレデューサーファイル(./reducers)から来ている場合。

0
kam bajwa
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
  };
}
0
kam bajwa

私は投稿と回答を読んでいますが、誰もが正しいです..しかし、依存関係にReduxPromiseがインストールされていない可能性があります..package.jsonファイルを確認してから、「npminstallredux-」を実行または再実行してください。 promise --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"**
0
Richard Rosario

私はまったく同じ問題を経験していました。ここでの問題は、ベースのindex.jsのミドルウェアにPromiseを適用しなかったことです。メインのindex.jsに、次のコード行を含める必要があります。

const createStoreWithMiddleware = applyMiddleware(promise)(createStore);

これで問題は解決します。

0
Chris