I am the developer of @teroneko/redux-saga-promise. It was initially forked from @adobe/redux-saga-promise but now it has been completelly revamped to use createAction from @reduxjs/toolkit to support TypeScript.
To keep in touch with the example of @ronen, here the TypeScript equivalent.
Create promise action (creator):
import { promiseActionFactory } from '@teroneko/redux-saga-promise'
export const fetchPostAction = promiseActionFactory<void>().create<{ id: string }>('FETCH_POST')
To dispatch a promise action (from creator):
// promiseMiddleware is required and must be placed before sagaMiddleware!
const store = createStore(rootReducer, {}, compose(applyMiddleware(promiseMiddleware, sagaMiddleware)))
await store.dispatch(fetchPostAction({ id: 'post-id' }))
To resolve/reject the promise action (from saga):
import { call, takeEvery } from 'redux-saga/effects'
import { implementPromiseAction } from '@teroneko/redux-saga-promise'
import { fetchPostAction } from './actions'
function * fetchPostSaga(action: typeof fetchPostAction.types.triggerAction) {
yield call(implementPromiseAction, action, function * () {
const { id } = action.payload
return yield call(apiCallToFetchPost, id)
})
// or for better TypeScript-support
yield call(fetchPostAction.sagas.implement, action, function * () {
const { id } = action.payload
return yield call(apiCallToFetchPost, id)
})
}
export function * rootSaga() {
yield takeEvery(fetchPostAction, fetchPostSaga);
}
So what's going on?
- promise action (creator) gets created
- promise action (from creator) gets created and
- dispatched to store.
- Then the promise action gets converted to a awaitable promise action where its deferred version is saved into the meta property. The action is immediatelly returned and
- passed to saga middleware.
- The now awaitable promise action is qualified to be used in implementPromiseAction that nothing else does than resolving or rejecting the deferred promise that is saved inside the meta property of the awaitable promise action.
See README for more features and advanced use cases.
posts
. Then do we need to have two states, one for the listposts
, and the other one for a single resource to edit/viewpost
? Is is the common/best practice? Actually I didn't want to add another state for a singlepost
. – Zadoc