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
を返します。その値にどのようにアクセスする必要がありますか?
編集:あなたが_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ミドルウェアを使用すると、非同期アクションを実行するたびに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)
を追加することを忘れないでください。
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'));
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)
);
}
メインの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;
}
正常に動作します
Index.js(ルートフォルダー)を開きます。
_import ReduxPromise from 'redux-promise';
_
const createStoreWithMiddleware = applyMiddleware(ReduxPromise)(createStore);
c。コードを再テストします。
メインのインデックスファイル(actionsフォルダーにあるファイルではなくsrcフォルダーにあるファイル)に移動し、次の行があることを確認します。
次のプロパティをプロバイダータグに追加します=> store = {createStoreWithMiddleware(reducers)}
レデューサーが結合されたレデューサーファイル(./reducers)から来ている場合。
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
};
}
私は投稿と回答を読んでいますが、誰もが正しいです..しかし、依存関係に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"**
私はまったく同じ問題を経験していました。ここでの問題は、ベースのindex.jsのミドルウェアにPromiseを適用しなかったことです。メインのindex.jsに、次のコード行を含める必要があります。
const createStoreWithMiddleware = applyMiddleware(promise)(createStore);
これで問題は解決します。