在我看来,在这种情况下没有正确/错误的模式。
我为你举了一个例子,说明如何使用 saga 实现你的目标。
基本思想:每个资源都有一个单独的 saga(例如,我曾经拆分为特征 saga),以及一个用于初始化的 saga。
然后主根 saga 将并行运行它们,您将能够在应用程序的某处触发初始化 saga 并让这一切发生:
注意:这个例子非常天真和简单,你应该找到一个更好的方法来组织所有东西,我只是尽量保持简单。
const {Provider, connect} = ReactRedux;
const {createStore, applyMiddleware} = Redux;
const createSagaMiddleware = ReduxSaga.default;
const {takeEvery, takeLatest} = ReduxSaga;
const {put, call, all, fork} = ReduxSaga.effects;
const initialState = {
fruits: [],
vegtables: []
};
const reducer = (state = initialState, action) => {
switch (action.type) {
case 'SET_FRUITS':
return {
...state,
fruits: [
...action.payload.fruits
]
}
case 'SET_VEGTABLES':
return {
...state,
vegtables: [
...action.payload.vegtables
]
}
}
return state;
};
//====== VEGTABLES ====== //
async function fetchVegtables() {
return await new Promise((res) => {
setTimeout(() => res([
'Cuecumber',
'Carrot',
'LEttuce'
]), 3000)
});
}
function* getVegtables() {
const vegtables = yield call(fetchVegtables);
yield put({ type: 'SET_VEGTABLES', payload: { vegtables } })
}
function* vegtablesSaga() {
yield takeEvery('GET_VEGTABLES', getVegtables);
}
//====== VEGTABLES ====== //
//====== FRUITS ====== //
async function fetchFruits() {
return await new Promise((res) => {
setTimeout(() => res([
'Banana',
'Apple',
'Peach'
]), 2000)
});
}
function* getFruits() {
const fruits = yield call(fetchFruits);
console.log(fruits)
yield put({ type: 'SET_FRUITS', payload: { fruits } })
}
function* fruitsSaga() {
yield takeEvery('GET_FRUITS', getFruits);
}
//====== FRUITS ====== //
//====== INIT ====== //
function* initData() {
yield all([
put({ type: 'GET_FRUITS' }),
put({ type: 'GET_VEGTABLES' })
]);
}
function* initSaga() {
yield takeLatest('INIT', initData);
}
//====== INIT ====== //
// Sagas
function* rootSaga() {
yield all([
yield fork(initSaga),
yield fork(fruitsSaga),
yield fork(vegtablesSaga),
]);
}
// Component
class App extends React.Component {
componentDidMount() {
this.props.dispatch({ type: 'INIT' });
}
render () {
return (
<div>
<div>fruits: {this.props.fruits.join()}</div>
<div>vegtables: {this.props.vegtables.join()}</div>
</div>
);
}
}
// Store
const sagaMiddleware = createSagaMiddleware();
const store = createStore(
reducer,
applyMiddleware(sagaMiddleware)
);
sagaMiddleware.run(rootSaga);
const ConnectedApp = connect((state) => ({
fruits: state.fruits,
vegtables: state.vegtables
}))(App);
// Container component
ReactDOM.render(
<Provider store={store}>
<ConnectedApp />
</Provider>,
document.getElementById('root')
);
如您所见,我有两种资源:水果和蔬菜。
每个资源都有自己的 saga,负责监视在某处调度的 GET 动作。
他们每个人都使用基本的 saga 效果(例如 call、put 等)来异步获取资源,然后将其分派到 store(然后 reducer 处理它们)。
此外,我设置了一个 initSaga,它使用 all 效果以并行方式触发所有资源获取 saga。
您可以在此处查看运行的整个示例:
https://jsfiddle.net/kadoshms/xwepoh5u/17/