react/redux action creator returns undefined when more than one payload
react/redux action creator returns undefined when more than one payload
嘿,这几天我一直在努力解决这个问题。我想在 reducer 中包含两条信息,一个 id 和收到的 json,但是到目前为止我所尝试的似乎没有用,对此的任何帮助将不胜感激。
这是使用 redux-multi 的根 index.js 文件:
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { createStore, applyMiddleware } from 'redux';
import { BrowserRouter, Route, Switch } from 'react-router-dom';
import promise from 'redux-promise';
import multi from 'redux-multi'
import reducers from './reducers';
import PhotosIndex from './components/photos_index';
import PhotosNew from './components/photos_new';
import PhotosShow from './components/photos_show';
const createStoreWithMiddleware = applyMiddleware(promise, multi)(createStore);
ReactDOM.render(
<Provider store={createStoreWithMiddleware(reducers)}>
<BrowserRouter>
<div>
<Switch>
<Route path="/photos/new" component={PhotosNew} />
<Route path="/photos/:id" component={PhotosShow} />
<Route path="/" component={PhotosIndex} />
</Switch>
</div>
</BrowserRouter>
</Provider>
, document.querySelector('.container'));
这是动作文件(动作文件夹 -> index.js)
import axios from 'axios';
export const FETCH_PHOTOS = 'fetch_photos';
export const DELETE_PHOTO = 'delete_photo';
const ROOT_URL = 'https://jsonplaceholder.typicode.com'
export function fetchPhotos(){
const request = axios.get(`${ROOT_URL}/photos`);
return {
type: FETCH_PHOTOS,
payload: request
};
}
export function deletePhoto(id){
const request = axios.get(`${ROOT_URL}/photos`);
const alldata = [id, request];
return {
type: DELETE_PHOTO,
//payload is undefined
payload: alldata
}
//also tried
//return {
// type: DELETE_PHOTO,
// id: id, - id is as expected
// payload: request - payload is undefined
//}
//also tried
//return {
// type: DELETE_PHOTO,
// id: id, - id is as expected
// payload: 'random string or any object' - payload is as expected
//}
}
这是减速器:
import _ from 'lodash';
import { FETCH_PHOTOS } from '../actions';
import { DELETE_PHOTO } from '../actions';
export default function(state = {}, action){
switch(action.type){
case FETCH_PHOTOS:
const first20 = action.payload.data.slice(0, 20);
console.log(first20);
return _.mapKeys(first20, 'id');
case DELETE_PHOTO:
//need to get two payloads into here, list of json elements and the id
//const first20_new = action.payload[1].data.slice(0, 20);
console.log(action.payload[1](data));
//console.log('first20 ' + first20_new);
console.log('data is: ' + action.payload[0]);
console.log('delete photo' + action.payload[1]);
// console.log('id is: ' + action.payload.data);
const findItemFromData = action.payload[1].indexOf(action.payload[0]);
console.log(findItemFromData);
// const removeItemFromData = action.payload.request.splice(findItemFromData, 1);
// return _.mapKeys(removeItemFromData, action.payload[0]);
default:
return state;
}
}
Axios 函数 return promise,不是同步值。查看用法示例 here。基本上,要访问您需要编写的响应
axios.get(`${ROOT_URL}/photos`)
.then(response => {
// do something with the response in here
});
您的动作创建者所写的问题是他们正在同步创建动作对象,而您还没有创建动作所需的数据。您必须等到 API 响应完成 returned 才能创建操作并发送它。您需要使用 redux-thunk
、redux-api-middleware
或 redux-saga
之类的东西来处理这些类型的异步创建的操作(或推出您自己的风格)。
例如,如果您使用 redux-thunk
,您的动作创建者将 return 一个函数,该函数传递给函数 dispatch
,它可用于在成功中调度动作您的 API 电话回拨。
function fetchPhotos() {
return (dispatch, getState) => {
// perform API call
axios.get(`${ROOT_URL}/photos`)
.then(response => {
// now that you have the response, you can dispatch the action
dispatch({
type: FETCH_PHOTOS,
payload: response
});
});
};
}
嘿,这几天我一直在努力解决这个问题。我想在 reducer 中包含两条信息,一个 id 和收到的 json,但是到目前为止我所尝试的似乎没有用,对此的任何帮助将不胜感激。
这是使用 redux-multi 的根 index.js 文件:
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { createStore, applyMiddleware } from 'redux';
import { BrowserRouter, Route, Switch } from 'react-router-dom';
import promise from 'redux-promise';
import multi from 'redux-multi'
import reducers from './reducers';
import PhotosIndex from './components/photos_index';
import PhotosNew from './components/photos_new';
import PhotosShow from './components/photos_show';
const createStoreWithMiddleware = applyMiddleware(promise, multi)(createStore);
ReactDOM.render(
<Provider store={createStoreWithMiddleware(reducers)}>
<BrowserRouter>
<div>
<Switch>
<Route path="/photos/new" component={PhotosNew} />
<Route path="/photos/:id" component={PhotosShow} />
<Route path="/" component={PhotosIndex} />
</Switch>
</div>
</BrowserRouter>
</Provider>
, document.querySelector('.container'));
这是动作文件(动作文件夹 -> index.js)
import axios from 'axios';
export const FETCH_PHOTOS = 'fetch_photos';
export const DELETE_PHOTO = 'delete_photo';
const ROOT_URL = 'https://jsonplaceholder.typicode.com'
export function fetchPhotos(){
const request = axios.get(`${ROOT_URL}/photos`);
return {
type: FETCH_PHOTOS,
payload: request
};
}
export function deletePhoto(id){
const request = axios.get(`${ROOT_URL}/photos`);
const alldata = [id, request];
return {
type: DELETE_PHOTO,
//payload is undefined
payload: alldata
}
//also tried
//return {
// type: DELETE_PHOTO,
// id: id, - id is as expected
// payload: request - payload is undefined
//}
//also tried
//return {
// type: DELETE_PHOTO,
// id: id, - id is as expected
// payload: 'random string or any object' - payload is as expected
//}
}
这是减速器:
import _ from 'lodash';
import { FETCH_PHOTOS } from '../actions';
import { DELETE_PHOTO } from '../actions';
export default function(state = {}, action){
switch(action.type){
case FETCH_PHOTOS:
const first20 = action.payload.data.slice(0, 20);
console.log(first20);
return _.mapKeys(first20, 'id');
case DELETE_PHOTO:
//need to get two payloads into here, list of json elements and the id
//const first20_new = action.payload[1].data.slice(0, 20);
console.log(action.payload[1](data));
//console.log('first20 ' + first20_new);
console.log('data is: ' + action.payload[0]);
console.log('delete photo' + action.payload[1]);
// console.log('id is: ' + action.payload.data);
const findItemFromData = action.payload[1].indexOf(action.payload[0]);
console.log(findItemFromData);
// const removeItemFromData = action.payload.request.splice(findItemFromData, 1);
// return _.mapKeys(removeItemFromData, action.payload[0]);
default:
return state;
}
}
Axios 函数 return promise,不是同步值。查看用法示例 here。基本上,要访问您需要编写的响应
axios.get(`${ROOT_URL}/photos`)
.then(response => {
// do something with the response in here
});
您的动作创建者所写的问题是他们正在同步创建动作对象,而您还没有创建动作所需的数据。您必须等到 API 响应完成 returned 才能创建操作并发送它。您需要使用 redux-thunk
、redux-api-middleware
或 redux-saga
之类的东西来处理这些类型的异步创建的操作(或推出您自己的风格)。
例如,如果您使用 redux-thunk
,您的动作创建者将 return 一个函数,该函数传递给函数 dispatch
,它可用于在成功中调度动作您的 API 电话回拨。
function fetchPhotos() {
return (dispatch, getState) => {
// perform API call
axios.get(`${ROOT_URL}/photos`)
.then(response => {
// now that you have the response, you can dispatch the action
dispatch({
type: FETCH_PHOTOS,
payload: response
});
});
};
}