Closed mtodberg closed 3 years ago
Yielding the initiate
thunk will return a Promise (even put
ing it in saga should do that), but keep in mind that that promise just returns the state after the thunk execution, no information if that query actually ran.
RTK-Q might decide that there is already a request in flight or that the state is just not stale (this can be skipped by forceRefetch: true
) and return immediately.
Edit: reworded "after the query" to "after the execution", since that Promise can even return before the first value is in the state - if it is fired while the first query is still running.
So in other words there are no way to bypass the rtk-q mechanisms? I noticed that I could do the following, but it's too much of a hack for me:
const response = yield put(fooApi.endpoints.foo.initiate(payload) as any); <-- has to be cast to any
const result = yield response; <-- returns raw api response
So in other words there are no way to bypass the rtk-q mechanisms?
Is your question right now "there is no way to use this while skipping over it's complete implementation?"?
Generally:
If put
does not accept thunks, you have to type it accordingly to be aware of your middleware - just as you need to type dispatch
accordingly to be aware of the thunk middleware.
Apart from the as any
, this is not a hack.
But I have to reiterate: Your code might return before the query has run for the first time, if you trigger it a second time while the exact same query with the same arguments is already running.
Better would probably to wait for the next completed a completion, so
// initiate query
const response = yield put(fooApi.endpoints.foo.initiate(payload), { forceRefetch: true })
// wait for finish
yield take(api.endpoints.foo.isFulfilled(payload))
// get result
const result = yield select(api.endpoints.foo.select(payload))
But generally, I'm not sure if you're really gonna be happy doing this - these APIs are not really meant to be used in an iterative way.
Your code example clears things up for me, thanks!
@phryneas FYI, created an issue in the redux-toolkit
repository as this basically another, yet highly related question when typing redux-saga's put
effect.
@phryneas Seems like there is no api.endpoints.foo.isFulfilled
. How do you wait for the ongoing request to finish?
Like this maybe?
// initiate query and wait for finish
yield yield put(fooApi.endpoints.foo.initiate(payload), { forceRefetch: true });
// get the result
const result = yield select(api.endpoints.foo.select(payload))
As I said, waiting for the returned promise will under some circumstances return before the fetch has finished. This API is not designed to be used in an imperative way.
It is meant for declarative consumption. It will at all times give you consistent data, but the timing should not be of your concern.
But to answer your question above, it is matchFulfilled
. See Docs: https://deploy-preview-1016--redux-starter-kit-docs.netlify.app/api/rtk-query/created-api/endpoints#matchers
I'm in the process of investigating if rtk-q fits into our large scale application. We are already using redux-toolkit and redux-saga. The sagas are for complicated async logic, in which we sometimes execute regular api requests. With rtk-q consolidating the endpoints in a single abstract structure, how can I perform the raw ajax request in a saga with something that returns a promise? Afaik, there are only the generated hooks and the thunk actioncreator way (
initiate
)?I want to do something like this in a saga: