Reputation: 517
In a hypothetical app, a user can create a book and by default that book has 3 pages. Once the book and pages are added, I want to do some other things with the book and pages. Books and Pages are two separate reducers in my redux store and also two tables in my database. My current flow is this:
As mentioned above, after Steps 4 and 5 get executed, I'd like to do some other things with the book, but I'm not sure the best approach for this. Just to get it running for now, currently I have a setTimeout function that runs checking for the new book and 3 pages with that bookId. If book and 3 pages are in the store, do other things, if not, run the timeout again. I feel very certain this is not the best way to do this. :smile:
Upvotes: 0
Views: 4643
Reputation: 621
You have a few options.
1) In your React Component, you could connect to the piece of state that is updated by your reducer when ADD_PAGES_SUCCESS. In componentWillReceiveProps
you could check for that connected piece of state, and dispatch the action you want to be done after step (5) from within your Component.
...not great because componentWillReceiveProps
can get hairy fast and should be avoided when possible.
2) Use redux-thunk or redux-saga:
With Redux-saga, in your ACTION handlers (sagas), you can take
ACTIONS and do things like conditionally make API calls and yield
(wait) for the server response, at which point you could trigger (put
) more ACTIONs or make more API calls or do anything else you want. This doesn't replace your reducers nor change your redux state.
Example:
// worker Saga: will be fired on ADD_PAGES_SUCCESS actions
function* doStuffAfterAddPages(action) {
while (true) {
yield take(ADD_PAGES_SUCCESS);
try {
let moreData;
const result = yield call(api.doSomethingElse);
if (result.isExpected) {
moreData = yield call(api.doOtherStuff);
} else {
moreData = yield call(api.doOtherStuff);
}
yield put(OTHER_STUFF_COMPLETE, { data: moreData });
} catch (error) {
yield put(OTHER_STUFF_FAILED, { error: error.message);
}
}
}
Upvotes: 0
Reputation: 67567
Gosha Arinich describes one possible solution in his post Detecting state changes with Redux-Saga.
In that post, he suggests writing a waitFor
function that would return when a provided selector finally returns true
:
function* waitFor(selector) {
if (yield select(selector)) return; // (1)
while (true) {
yield take('*'); // (1a)
if (yield select(selector)) return; // (1b)
}
}
It could be used like this:
function* someSaga() {
yield call(waitFor, state => getCurrentUser(state) != null);
// the user is logged in by now
}
Another possible solution would be a simpler custom middleware that does that checking after actions are dispatched.
Upvotes: 8