Request creators
See original GitHub issueRight now we create requests like this:
const fetchBook = id => ({
type: 'FETCH_BOOK',
request: { url: `/books/${id}` },
meta: { requestKey: id },
});
This is problematic due to the following reasons:
- no autocomplete, unless you use TS and
RequestAction
interface, but with pure JS you won’t get autocomplete at all - it is just redux action, it requires to have constant and action separately, however often we need both to a function like
useQuery
,type
is needed for selector and action is needed to be called to automatically fetch - issue from point 2 is of course solvable by using action creator library, which adds constant automatically and adds
toString
method returning this type, so that action becomes both action itself and source of its type, I mean libraries likeredux-act
,redux-actions
and myredux-smart-actions
- but 3 is hard to explain to many new Redux developers, and probably just impossible totally for people not knowing Redux, and asking to use constants looks pretty bad, API won’t look attractive, and telling people to use action creator library will also look weird, especially the goal is to use this lib even by people not knowing Redux, right now it is already possible with the latest React release
So, suggestion? For instance helper like createQuery
, which could work like that:
const fetchBook = createQuery(
'FETCH_BOOK',
id => ({ url: `/books/${id}` }), // driverConfig, will go to `request`
id => ({ requestKey: id }), // requestOptions, will go to `meta`
}));
Then, fetchBook(1)
will return the same what previous version, but fetchBook.toString() === 'FETCH_BOOK'
, so no constants anymore.
What we gain?
5) autocomplete
6) No reason to explain why we need constants for people not knowing Redux
7) We could do nice stuff, like inject meta.variables
which might be nice source of info, we know also whether request is query or mutation, so we won’t need things like meta.asQuery
anymore
8) createQuery
etc could have some generics, which could be filled with drivers like axios driver, then you could import createQuery
from a driver and also have driver config typed and autocompleted
This would be not breakable, current way of writing would also work, but in the next major version:
9) API simplification, useQuery
won’t have action
prop anymore, as type will be always action creator, never string
10) I would really remove support for FSA action, no payload.request
, just request
, this really shouldn’t matter, and library could be simplified
But are there any disadvantages? I cannot see, but maybe I miss some, please write if anything comes to your mind!
Issue Analytics
- State:
- Created 3 years ago
- Reactions:1
- Comments:14 (8 by maintainers)
@avasuro thx for your analysis, indeed it looks like going FSA all the way could be the best option. Actually we almost have FSA anyway, as we use
meta
convention. We could even changerequest
intopayload
without nestingrequest
inpayload
, because probably next version will recognize request actions and queries differently. Probably we will just have a new mandatorymeta.requestType: 'QUERY' | 'MUTATION' | 'SUBSCRIPTION'
I know this is quite a big change, but this will be for a reason. Not for all drivers it is possible to deduct whether it is query or mutation. For example, for promise driver it is always necessary to pass
meta.asQuery
. This will also simplify many things, for example we could removeisRequestAction
andisRequestActionQuery
fromhandleRequests
config, as adjusting this won’t be necessary anymore -meta.requestType
will tell us all explicitely about the type.But with
createQuery
and family,meta.requestType
will be added just automatically. I think we could also addmeta.variables
automatically, then we could use this info for example to make effecttakeLeading
instead oftakeLatest
for a query by default, because without variables it doesn’t really make sense to abort previous pending query and start a new one, it would be a nice optimisation, done automatically for the user. But this requires obligatory usage ofcreateQuery
helpers (in theory one could do this manually, but why?). And frankly, I don’t understand why someone would use redux-act etc ascreateQuery
will do the very same thing, but a little more. But, perhaps FSA should be enforced, as then all will be compatible withcreateReducer
of many libraries likeredux-act
, which require FSA structure.Also, I have some more plans for action creator helpers - one of my TODO is adding support for offline mutations - they will be queued when offline, and could be auto dispatched when going back online. But callbacks are not serializable, so we cannot just save mutations to local storage for example and recreate them on reload when going online. But I am pretty sure I will be able to mitigate it with some alternatives, thx to nothing else than request creators. This is yet another argument to really enforce usage of this, but in the docs we should of course explain, what it does under the hood, so Redux users will understand what’s going on behind the scenes
@avasuro Good points. The question is then, will all people use createQuery, createMutation and createSubscription helpers? In my opinion yes, and in fact this way will be advocated in all examples and documentations. This is the only way I can show nice API in examples, without duplicating action and constant imports in places like
useQuery
.But, if not, if some people preferred not using those helpers, then it would be enough to support fsa request actions in reducers and middleware, helpers themselves wouldn’t need to support fsa flag.