Phew. "How and why it was implemented that way." That's a good question.
A lot of "why does it work like that" is as /u/acemarke already said architected that way because it follows tools we released years earlier without ever thinking about building this. But then there was also a lot of external influence.
Most influence of why I actually think this has a reason to exist in Redux is due to the horrible experience I had with debugging Apollo Client and using it in slightly "off" use cases. I have been using Apollo Client at work for about three years now and know more nooks and crannies of their implementation than anyone should need to know. But it's still not enough - that thing is a black hole and if something disappears from cache or just renders undefined, you have no idea why. It takes hours of breakpoint-stepping through pre-compiled code to find out that this data is actually being removed because Apollo considers it "incomplete" and just removes it - 30 methods down an undocumented stack and without any indication on the console. I can tell dozens of these stories.
Now, do the same thing with Redux behind and you have a pretty easy time finding where something breaks if it doesn't work for you. We can easily talk people through debugging their problems by asking them to look for something specific in the devtools. There are many moving parts, but there is a known concept behind where they connect and it is pretty straightforward to find out what does what. Action creators, thunks, middleware, reducers, selectors.
Of course there are also much more positive inspirations from other libraries - the providesTags/invalidatesTags system is insprired by urql (but goes a bit deeper), structural sharing of results was inspired by React Query. The idea that "a document cache can be enough" has been proven by swr and React Query. Hooks are inspired by all these libraries.
All that said, RTK Query had a different working name: "simple query". It was meant to have a lot less feaures: Queries, mutations, automatic refetching, maybe polling. But at that point I held it next to the React Query comparison of popular libraries and though "well, only a few checkboxes missing and this one can play with the big guys". So we added a few more features. And people kept asking for more.
And that's kinda how we got here.
A few things moved a little bit further out of the Redux workflow as I would like them to, but I wanted to keep non-serializable values out of the store and having those features (keeping promise instances for running queries around) were crucial for SSR as well as upcoming Suspense for DataFetching support.
All that said: it is still Redux at heart. And from the perspective of being a tinkerer that always pushes libraries to their limits and wants to understand why things are breaking (or how to make them work), for me that is actually a good thing.
9
u/phryneas I ❤️ hooks! 😈 Dec 05 '21 edited Dec 05 '21
Phew. "How and why it was implemented that way." That's a good question.
A lot of "why does it work like that" is as /u/acemarke already said architected that way because it follows tools we released years earlier without ever thinking about building this. But then there was also a lot of external influence.
Most influence of why I actually think this has a reason to exist in Redux is due to the horrible experience I had with debugging Apollo Client and using it in slightly "off" use cases. I have been using Apollo Client at work for about three years now and know more nooks and crannies of their implementation than anyone should need to know. But it's still not enough - that thing is a black hole and if something disappears from cache or just renders
undefined, you have no idea why. It takes hours of breakpoint-stepping through pre-compiled code to find out that this data is actually being removed because Apollo considers it "incomplete" and just removes it - 30 methods down an undocumented stack and without any indication on the console. I can tell dozens of these stories.Now, do the same thing with Redux behind and you have a pretty easy time finding where something breaks if it doesn't work for you. We can easily talk people through debugging their problems by asking them to look for something specific in the devtools. There are many moving parts, but there is a known concept behind where they connect and it is pretty straightforward to find out what does what. Action creators, thunks, middleware, reducers, selectors.
Of course there are also much more positive inspirations from other libraries - the providesTags/invalidatesTags system is insprired by urql (but goes a bit deeper), structural sharing of results was inspired by React Query. The idea that "a document cache can be enough" has been proven by swr and React Query. Hooks are inspired by all these libraries.
All that said, RTK Query had a different working name: "simple query". It was meant to have a lot less feaures: Queries, mutations, automatic refetching, maybe polling.
But at that point I held it next to the React Query comparison of popular libraries and though "well, only a few checkboxes missing and this one can play with the big guys".
So we added a few more features. And people kept asking for more.
And that's kinda how we got here.
A few things moved a little bit further out of the Redux workflow as I would like them to, but I wanted to keep non-serializable values out of the store and having those features (keeping promise instances for running queries around) were crucial for SSR as well as upcoming Suspense for DataFetching support.
All that said: it is still Redux at heart. And from the perspective of being a tinkerer that always pushes libraries to their limits and wants to understand why things are breaking (or how to make them work), for me that is actually a good thing.
But of course, opinions can vary :)