redux-saga:操作必须是普通对象
redux-saga: Actions must be plain objects
我的 saga 有问题,我不知道哪里出了问题。我收到类似 Actions must be plain objects 的错误。在使用 React Redux 时使用自定义中间件进行异步操作。这是我的代码。
container/index.js
class AppContainer extends Component {
componentDidMount() {
const { actions: { onFetchPhoto } } = this.props;
onFetchPhoto();
}
render() {
return (
<App />
);
}
}
const mapDispatchToProps = (dispatch) => ({
actions: {
onFetchPhoto: () => dispatch(fetchPhoto())
}
})
export default connect(null, mapDispatchToProps)(AppContainer);
actions/index.js
export const FETCH_PHOTO_REQUEST = "FETCH_PHOTO_REQUEST";
export const FETCH_PHOTO_SUCCESS = "FETCH_PHOTO_SUCCESS";
export const FETCH_PHOTO_FAILURE = "FETCH_PHOTO_FAILURE";
export function fetchPhoto(payload) {
return {
type: FETCH_PHOTO_REQUEST
}
}
export function fetchPhotoSuccess(payload) {
return {
type: FETCH_PHOTO_SUCCESS,
payload
}
}
export function fetchPhotoFailure(error) {
return {
type: FETCH_PHOTO_SUCCESS,
payload: {
error
}
}
}
sagas/index.js
function* fetchRandomPhoto() {
//yield put(fetchPhoto());
const {
response,
error
} = yield call(fetchRandomPhotoApi)
if (response) {
yield put(fetchPhotoSuccess(response))
} else {
yield put(fetchPhotoFailure(error))
}
}
function* watchLoadRandomPhoto() {
try {
while (true) {
yield takeLatest(FETCH_PHOTO_REQUEST, fetchRandomPhoto);
}
}
catch(error) {
console.error("error in saga", error)
}
}
export default function* rootSaga() {
yield fork(watchLoadRandomPhoto)
}
services/index.js
import axios from 'axios';
import {
URL,
PUBLIC_KEY
} from 'src/constants/config';
import {
schema,
normalize
} from 'normalizr'
export function fetchRandomPhotoApi() {
return axios({
url: `${URL}/photos/random`,
timeout: 10000,
method: 'get',
headers: {
'Autorization': `Client-ID ${PUBLIC_KEY}`
},
responseType: 'json'
})
.then((response) => {
const { data } = response.data;
console.log("d");
if (data) {
return ({
response: {
id: data.id,
url: data.urls.full,
title: data.location.title
}
})
}
})
.catch(error => error)
}
store/configureStore.js
import rootReducer from 'src/reducers/root';
import rootSaga from 'src/sagas';
export default function configureStore() {
const logger = createLogger();
const sagaMiddleware = createSagaMiddleware();
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
const store = createStore(
rootReducer,
compose(
applyMiddleware(
sagaMiddleware,
logger,
composeEnhancers
),
)
);
sagaMiddleware.run(rootSaga);
return store;
}
我浪费了 2 天的时间来解决这个问题,但没有结果。 Chrome 向我展示了这个错误:
问题的根源在于 fetchRandomPhotoApi 函数。不知道它看起来像什么我不能肯定地说但是如果它是一个函数 return 你应该调用像
的承诺
const { response, error } = yield call(fetchRandomPhotoApi)
请注意调用中缺少括号。
更新
从你的编辑中我现在可以看到你的 api 调用中的承诺没有得到解决。您希望该函数 return 一个对象而不是传递给您的操作的实际承诺。类似于:
axios({...etc}).then(response => response).catch(error => error)
好吧,我找到了我的问题,但我不明白为什么。我添加了这段代码。
store/index.js
export default function configureStore() {
const logger = createLogger();
const sagaMiddleware = createSagaMiddleware();
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
const store = createStore(
rootReducer,
compose(
applyMiddleware(
sagaMiddleware,
logger
),
window.__REDUX_DEVTOOLS_EXTENSION__ ? window.__REDUX_DEVTOOLS_EXTENSION__() : (fn) => fn
)
);
store.runSaga = sagaMiddleware.run;
return store;
}
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import configureStore from 'src/store/configureStore';
import Routes from 'src/routes/root';
import rootSaga from 'src/sagas';
const store = configureStore();
store.runSaga(rootSaga);
ReactDOM.render(
<Provider store={store}>
<Routes store={store} />
</Provider>,
document.getElementById('root')
);
这一行也让我的应用程序工作。
window.__REDUX_DEVTOOLS_EXTENSION__ ? window.__REDUX_DEVTOOLS_EXTENSION__() : (fn) => fn
我的 saga 有问题,我不知道哪里出了问题。我收到类似 Actions must be plain objects 的错误。在使用 React Redux 时使用自定义中间件进行异步操作。这是我的代码。
container/index.js
class AppContainer extends Component {
componentDidMount() {
const { actions: { onFetchPhoto } } = this.props;
onFetchPhoto();
}
render() {
return (
<App />
);
}
}
const mapDispatchToProps = (dispatch) => ({
actions: {
onFetchPhoto: () => dispatch(fetchPhoto())
}
})
export default connect(null, mapDispatchToProps)(AppContainer);
actions/index.js
export const FETCH_PHOTO_REQUEST = "FETCH_PHOTO_REQUEST";
export const FETCH_PHOTO_SUCCESS = "FETCH_PHOTO_SUCCESS";
export const FETCH_PHOTO_FAILURE = "FETCH_PHOTO_FAILURE";
export function fetchPhoto(payload) {
return {
type: FETCH_PHOTO_REQUEST
}
}
export function fetchPhotoSuccess(payload) {
return {
type: FETCH_PHOTO_SUCCESS,
payload
}
}
export function fetchPhotoFailure(error) {
return {
type: FETCH_PHOTO_SUCCESS,
payload: {
error
}
}
}
sagas/index.js
function* fetchRandomPhoto() {
//yield put(fetchPhoto());
const {
response,
error
} = yield call(fetchRandomPhotoApi)
if (response) {
yield put(fetchPhotoSuccess(response))
} else {
yield put(fetchPhotoFailure(error))
}
}
function* watchLoadRandomPhoto() {
try {
while (true) {
yield takeLatest(FETCH_PHOTO_REQUEST, fetchRandomPhoto);
}
}
catch(error) {
console.error("error in saga", error)
}
}
export default function* rootSaga() {
yield fork(watchLoadRandomPhoto)
}
services/index.js
import axios from 'axios';
import {
URL,
PUBLIC_KEY
} from 'src/constants/config';
import {
schema,
normalize
} from 'normalizr'
export function fetchRandomPhotoApi() {
return axios({
url: `${URL}/photos/random`,
timeout: 10000,
method: 'get',
headers: {
'Autorization': `Client-ID ${PUBLIC_KEY}`
},
responseType: 'json'
})
.then((response) => {
const { data } = response.data;
console.log("d");
if (data) {
return ({
response: {
id: data.id,
url: data.urls.full,
title: data.location.title
}
})
}
})
.catch(error => error)
}
store/configureStore.js
import rootReducer from 'src/reducers/root';
import rootSaga from 'src/sagas';
export default function configureStore() {
const logger = createLogger();
const sagaMiddleware = createSagaMiddleware();
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
const store = createStore(
rootReducer,
compose(
applyMiddleware(
sagaMiddleware,
logger,
composeEnhancers
),
)
);
sagaMiddleware.run(rootSaga);
return store;
}
我浪费了 2 天的时间来解决这个问题,但没有结果。 Chrome 向我展示了这个错误:
问题的根源在于 fetchRandomPhotoApi 函数。不知道它看起来像什么我不能肯定地说但是如果它是一个函数 return 你应该调用像
的承诺const { response, error } = yield call(fetchRandomPhotoApi)
请注意调用中缺少括号。
更新
从你的编辑中我现在可以看到你的 api 调用中的承诺没有得到解决。您希望该函数 return 一个对象而不是传递给您的操作的实际承诺。类似于:
axios({...etc}).then(response => response).catch(error => error)
好吧,我找到了我的问题,但我不明白为什么。我添加了这段代码。
store/index.js
export default function configureStore() {
const logger = createLogger();
const sagaMiddleware = createSagaMiddleware();
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
const store = createStore(
rootReducer,
compose(
applyMiddleware(
sagaMiddleware,
logger
),
window.__REDUX_DEVTOOLS_EXTENSION__ ? window.__REDUX_DEVTOOLS_EXTENSION__() : (fn) => fn
)
);
store.runSaga = sagaMiddleware.run;
return store;
}
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import configureStore from 'src/store/configureStore';
import Routes from 'src/routes/root';
import rootSaga from 'src/sagas';
const store = configureStore();
store.runSaga(rootSaga);
ReactDOM.render(
<Provider store={store}>
<Routes store={store} />
</Provider>,
document.getElementById('root')
);
这一行也让我的应用程序工作。
window.__REDUX_DEVTOOLS_EXTENSION__ ? window.__REDUX_DEVTOOLS_EXTENSION__() : (fn) => fn