-
Notifications
You must be signed in to change notification settings - Fork 1k
redux-thunk not waiting for my promise to be fulfilled #52
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
I tested now with latest versions and severals actions and I always receive the following type of error if wrapped in a promise:
If I reorganise my flow into resolving the promise first and then calling a normal non-async action it works perfectly fine. I do not make any modifications |
I'm having the same issue since upgrading to React Native 0.19 |
I'm having the same problem with async actions. // actionCreator
export function asyncAction () {
return dispatch => api().then(data => data.id)
}
// component
dispatch(asyncAction()).then(() => console.log('done'));
// => Cannot read property 'then' of undefined Love the library btw 👍 |
The library code has not changed since its initial release. I have two guesses why this might be happening. Are you using the new API without updating to Redux 3.1.0?// Note: this API requires redux@>=3.1.0
const store = createStore(
rootReducer,
applyMiddleware(thunk)
); Before 3.1.0, you had to do this: const createStoreWithMiddleware = applyMiddleware(thunk)(createStore)
const store = createStoreWithMiddleware(rootReducer);
|
My second suggestion is incorrect. Existing store enhancers should work fine as long as you don’t mix the new and the old styles of applying them. So this is potentially problematic (depending on whether the store enhancer has been updates to match 3.1 API): // Potentially problematic
const finalCreateStore = someStoreEnhancer()(createStore)
const store = finalCreateStore(reducer, applyMiddleware(thunk)) If you have code like this, either convert it fully to the old style: // Works with any version of redux
const finalCreateStore = compose(
someStoreEnhancer(),
applyMiddleware(thunk)
)(createStore)
const store = finalCreateStore(reducer) or to the new style: // Works only with redux >= 3.1.0
const store = createStore(
reducer,
compose(
someStoreEnhancer(),
applyMiddleware(thunk)
)
) Just make sure you don't mix these styles. |
In any case, there is nothing further I can do to help unless you post a complete project reproducing the issue. |
@gaearon here is a plunker demonstrating the effect: The error is thrown before the promise is fulfilled. If you wrap the dispatch in a promise |
I also tried wrapping the various parts of the async thunk into |
@gaearon and another plunker not involving Angular at all: |
In your second example: return setTimeout(() => {
console.log('save-async-resolved')
return dispatch(_save(name))
}, 2000)
To fix this, you want to create a Promise-friendly wrapper for timeout. For example: function delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms))
}
// later
return delay(2000).then(() => {
console.log('save-async-resolved')
return dispatch(_save(name))
}) |
The problem with the first example is exactly the same: the mistaken assumption that Finally, note that Redux Thunk does not require you to use Promises. Thunk dispatches will return whatever you return from thunks. But Promises are usually handy so we suggest using them. Just make sure you actually return Promises and not something else. |
In my real app I don't use setTimeout but a promise. I will update my plunker and come back to you. |
Please provide the exact example that fails. People spend time helping reproduce issues, so it is essential that you provide the exact code that fails rather than an approximation that fails for a different reason. Thank you! |
Sorry, my fault. Am new to all of this. I updated my plunks: |
Thank you very much for the complete example. In your code, dispatch (action): any {
this._store.dispatch(action)
// should have been:
// return this._store.dispatch(action)
} This is why .then((res) => {
return this._storeService.dispatch(this._nameActions.save('Redux'))
}) does not actually wait for the async action to finish, and the promise immediately resolves. Be careful to always return Promises if you want to wait for them 😉 |
@nicohvi If you have this problem, please also post the full example reproducing it. It’s hard to say at which point return value got lost for you. It could be due to a middleware that forgets to return it, a bad middleware configuration, etc. |
Damn it, I copied this from https://github.com/jhades/angular2-redux-store because I thought he would know. I will drop him a note. Thanks a million! |
Easy to overlook if they didn’t use async middleware yet. Thank you for bringing this up! |
It was a faulty store setup @gaearon, thank you very much for pointing me in the right direction 👍 |
To add to @gaearon's example, if you need to pass in initialState, per the createStore api documentation: // Works only with redux >= 3.1.0
let initialState = {};
const store = createStore(
reducer,
initialState,
compose(
someStoreEnhancer(),
applyMiddleware(thunk)
)
) This got me a little tripped up, so I hope it helps someone else. |
is compose needed anymore? the docs don't mention it. thanks. |
I have the following setup following your examples for chaining async actions:
What happens is that the flow is like this:
For one reason or another store.dispatch resolves before myAsyncApiCall is resolved.
I either receive then a TypeError or if wrapping the whole into a promise an undefined action error.
Any idea?
The text was updated successfully, but these errors were encountered: