Reputation: 5055
I have a watcher saga that is constantly listening for actions of a certain type. This is started up from the saga.run(). When it receives an action of a certain type, it should then call into another saga which performs async actions. However a breakpoint inside the second saga is never getting called.
So either the originating code is not dispatching the action correctly, or the watcher saga is configured wrong.
Watcher saga code
import { all, fork, takeLatest } from 'redux-saga/effects'
import {fetchItems} from './itemsSaga';
function* watchLoadItemsRequest() {
while(true) {
yield takeLatest('FETCH_ITEMS_REQUEST', fetchItems);
}
}
export default function* root() {
yield all ([
fork(watchLoadItemsRequest)
])
}
My itemsSaga (that isn't being called)
import { call, put } from 'redux-saga/effects'
import fetchItemsCompleted from '../actions/fetchItemsCompleted';
import httpCallCompleted from '../actions/httpCallCompleted';
import httpCallStarted from '../actions/httpCallStarted';
import itemAPI from '../api/itemAPI';
import ItemsEntity from '../api/itemEntity';
// worker Saga: will be fired on FETCH_ITEMS_REQUEST actions
export function* fetchItems(action:any) {
let items : ItemEntity[];
yield put(httpCallStarted());
trades = yield call(itemAPI.getAllItemsAsync)
trades = [new ItemEntity(), new ItemEntity()]
yield put(fetchItemsCompleted(items))
yield put(httpCallCompleted());
}
My store creation code
import { applyMiddleware, createStore } from 'redux';
import createSagaMiddleware from 'redux-saga';
import reducers from '../reducers';
import watchersSaga from '../sagas/watchersSaga';
export default function getStore() {
const sagaMiddleware = createSagaMiddleware();
const store = createStore(
reducers, applyMiddleware(sagaMiddleware)
);
sagaMiddleware.run(watchersSaga);
return store;
}
And lastly the control which should send the FETCH_ITEMS_REQUEST action
import * as React from 'react';
import { connect, Dispatch } from 'react-redux';
import ItemEntity from './api/itemEntity';
import './App.css';
import IStoreState from './interfaces/IStoreState';
interface IContentProps {
groupingType : string,
items: ItemEntity[],
loadItems : () => void
}
class MyContent extends React.Component<IContentProps,{}> {
constructor(props: any) {
super(props);
}
public componentDidMount() {
this.props.loadItems();
}
public render() {
return (
<div className="Center-content">
<div className="Center-content White">
<br/><br/>Grouped by {this.props.groupingType}<br/><br/>{this.props.items.length} items loaded
</div>
</div>
);
}
}
function mapStateToProps(state: IStoreState) {
return {
groupingType: state.navigation.groupingType,
trades: state.item.items
};
}
const mapDispatchToProps = (dispatch: Dispatch) => {
return {
loadItems: () => dispatch({type:'FETCH_ITEMS_REQUEST'})
}
}
export default connect(mapStateToProps, mapDispatchToProps)(PnlContent);
Why isn't this working? Is there a way I can tell whether or not the FETCH_ITEMS_REQUEST is actually being generated and sent to redux or not? That way at least I could narrow down where the problem is occurring.
UPDATE: I've tweaked one of my reducers to listen to the FETCH_ITEMS_REQUEST and it picks up the event, so my control is dispatching the action fine. It just seems the WatcherSaga is not triggering the ItemsSaga fetchItems() method when it receives a FETCH_ITEMS_REQUEST action so I think the problem is in my watchersSaga
SECOND UPDATE:
More and more I think the problem lies with the lines
while(true) {
yield takeLatest('FETCH_ITEMS_REQUEST', fetchItems);
}
This doesn't seem to be responding to a received FETCH_ITEMS_REQUEST message and calling fetchItems
Upvotes: 2
Views: 3105
Reputation: 5055
For anyone with a similar problem I ended up solving it by changing my watchers Saga to the following
function* watchLoadTradesRequest() {
yield takeEvery('FETCH_TRADES_REQUEST', fetchTrades);
}
// Register all your watchers
export default function* watchersRootSaga() {
yield all ([
watchLoadTradesRequest()
])
}
Upvotes: 5