Reactjs Reducer未在启动操作时更新状态,因此redux存储/状态未更新
从mediaSagas.js启动的操作没有进入reducer函数,因此reducer存储/状态没有更新。 我已尝试调试,但无法找到根本原因 actionTypes.jsReactjs Reducer未在启动操作时更新状态,因此redux存储/状态未更新,reactjs,redux,react-redux,redux-saga,Reactjs,Redux,React Redux,Redux Saga,从mediaSagas.js启动的操作没有进入reducer函数,因此reducer存储/状态没有更新。 我已尝试调试,但无法找到根本原因 actionTypes.js export const FLICKR_IMAGES_SUCCESS = 'FLICKR_IMAGES_SUCCESS'; export const SHUTTER_VIDEOS_SUCCESS = 'SHUTTER_VIDEOS_SUCCESS'; imageReducer.js import initialState fr
export const FLICKR_IMAGES_SUCCESS = 'FLICKR_IMAGES_SUCCESS';
export const SHUTTER_VIDEOS_SUCCESS = 'SHUTTER_VIDEOS_SUCCESS';
imageReducer.js
import initialState from './initialState';
import * as types from '../constants/actionTypes';
export default function (state = initialState.images, action) {
console.log("action",action); // I am not getting action with type FLICKR_IMAGES_SUCCESS or SHUTTER_VIDEOS_SUCCESS
switch (action.type) {
case types.FLICKR_IMAGES_SUCCESS:
return [...state, action.images];
default:
return state;
}
}
import initialState from './initialState';
import * as types from '../constants/actionTypes';
export default function (state = initialState.videos, action) {
console.log("action",action); // I am not getting action with type FLICKR_IMAGES_SUCCESS or SHUTTER_VIDEOS_SUCCESS
switch (action.type) {
case types.SHUTTER_VIDEOS_SUCCESS:
return [...state, action.videos];
default:
return state;
}
}
videoReducer.js
import initialState from './initialState';
import * as types from '../constants/actionTypes';
export default function (state = initialState.images, action) {
console.log("action",action); // I am not getting action with type FLICKR_IMAGES_SUCCESS or SHUTTER_VIDEOS_SUCCESS
switch (action.type) {
case types.FLICKR_IMAGES_SUCCESS:
return [...state, action.images];
default:
return state;
}
}
import initialState from './initialState';
import * as types from '../constants/actionTypes';
export default function (state = initialState.videos, action) {
console.log("action",action); // I am not getting action with type FLICKR_IMAGES_SUCCESS or SHUTTER_VIDEOS_SUCCESS
switch (action.type) {
case types.SHUTTER_VIDEOS_SUCCESS:
return [...state, action.videos];
default:
return state;
}
}
initialState.js
export default {
images: [],
videos: []
};
mediaSagas.js
import { put, call } from 'redux-saga/effects';
import { unsplashImages, shutterStockVideos } from '../Api/api';
import * as types from '../constants/actionTypes';
export default function* searchMediaSaga({ payload }) {
console.log("saga entered");
try {
const videos = yield call(shutterStockVideos, payload);
const images = yield call(unsplashImages, payload);
console.log("vids",videos); // I am getting the videos data here
console.log("img",images); // I am getting the image data here
yield [
put({ type: types.SHUTTER_VIDEOS_SUCCESS, videos }),
put({ type: types.FLICKR_IMAGES_SUCCESS,images}),
];
} catch (error) {
console.log("err",error);
yield put({ type: 'SEARCH_MEDIA_FAILURE', error });
}
}
watchers.js
import { takeLatest } from 'redux-saga/effects';
import searchMediaSaga from './mediaSagas';
import * as types from '../constants/actionTypes';
// Watches for SEARCH_MEDIA_REQUEST action type asynchronously
export default function* watchSearchMedia() {
yield takeLatest(types.SEARCH_MEDIA_REQUEST, searchMediaSaga);
}
reducers/index.js
import { combineReducers } from 'redux';
import images from './imageReducer';
import videos from './videoReducer';
const rootReducer = combineReducers({
images,
videos
});
export default rootReducer;
import { fork } from 'redux-saga/effects';
import watchSearchMedia from './watchers';
export default function* startForman() {
yield fork(watchSearchMedia);
}
sagas/index.js
import { combineReducers } from 'redux';
import images from './imageReducer';
import videos from './videoReducer';
const rootReducer = combineReducers({
images,
videos
});
export default rootReducer;
import { fork } from 'redux-saga/effects';
import watchSearchMedia from './watchers';
export default function* startForman() {
yield fork(watchSearchMedia);
}
configureStore.js
import { createStore, applyMiddleware } from 'redux';
import createSagaMiddleware from 'redux-saga';
import rootReducer from '../reducers/index';
import rootSaga from '../sagas'; // TODO: Next step
const configureStore = () => {
const sagaMiddleware = createSagaMiddleware();
return {
...createStore(rootReducer,
applyMiddleware(sagaMiddleware)),
runSaga: sagaMiddleware.run(rootSaga)
};
};
export default configureStore;
src/index.js
import ReactDOM from 'react-dom';
import React from 'react';
import {
BrowserRouter as Router,
Route,
Switch
} from "react-router-dom";
import { Provider } from 'react-redux';
import configureStore from './store/configureStore';
import App from './containers/App'
import MediaGalleryPage from './containers/MediaGalleryPage'
const store = configureStore();
store.subscribe(() => {
const newState = store.getState();
// check out your updated state
console.log("NewState", newState) // always giving empty image and video arrays
});
ReactDOM.render(
<Provider store={store}>
<Router>
<Switch>
<Route exact path="/" component={App} />
<Route path="/library" component={MediaGalleryPage} />
</Switch>
</Router>
</Provider>, document.getElementById('root')
);
从“react dom”导入ReactDOM;
从“React”导入React;
进口{
BrowserRouter作为路由器,
路线,,
转换
}从“反应路由器dom”;
从'react redux'导入{Provider};
从“/store/configureStore”导入configureStore;
从“./containers/App”导入应用程序
从“./containers/MediaGalleryPage”导入MediaGalleryPage
const store=configureStore();
store.subscribe(()=>{
const newState=store.getState();
//查看您的更新状态
console.log(“NewState”,NewState)//始终提供空的图像和视频数组
});
ReactDOM.render(
,document.getElementById('root'))
);
我发现了这个问题,在mediaSagas.js中,我并行使用了put-effect,但我现在使用的方式已经不推荐了。检查解决我问题的redux saga文档中的所有([…效果])-并行效果
正如我在上面使用的不推荐的方法-
yield [
put({ type: types.SHUTTER_VIDEOS_SUCCESS, videos }),
put({ type: types.FLICKR_IMAGES_SUCCESS,images}),
];
解决我问题的新方法(正确方法)
yield all([
put({ type: types.SHUTTER_VIDEOS_SUCCESS, videos }),
put({ type: types.FLICKR_IMAGES_SUCCESS,images })
]);
Github链接,它为我指明了解决方案-
是否调用了saga?@elvis_-ferns:是的,saga正在调用,我正在从APIA获取数据并行使用put effect有什么用?@elvis_-ferns:根据文档定义所有效果-创建一个效果描述,指示中间件并行运行多个效果,并等待所有效果完成。它与标准Promise完全对应。我没有单独编写put effect并等待它们中的每一个,而是使用了并行put,因为不管怎样,我需要等待它们完成并行并不意味着并行。状态将在不同的时间触发我不确定状态将如何更新,但我使用put effect parallely/yieldall的原因是因为我的多个put不依赖于彼此来完成,它们可以一次触发。如果存在依赖关系,我会单独使用收益率