Skip to content
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

Automatic normalization addon to rtk-query #4073

Open
klis87 opened this issue Jan 12, 2024 · 2 comments
Open

Automatic normalization addon to rtk-query #4073

klis87 opened this issue Jan 12, 2024 · 2 comments
Labels
enhancement New feature or request rtk-query

Comments

@klis87
Copy link

klis87 commented Jan 12, 2024

Hi, as discussed in #3248 , I integrated rtk-query with normy, a library, which allows automatic normalization and data updates for fetching libraries. There is already react-query and swr integration, now also rtk-query is supported. You can find it here - https://github.com/klis87/normy/tree/master/packages/normy-rtk-query#normyrtk-query

This is to solve problem mentioned here - https://redux-toolkit.js.org/rtk-query/comparison#no-normalized-or-deduplicated-cache and gives you apollo graphql like experience - relevant queries are automatically updated based on mutations results with no additional code.

I raised this issue not only as information, but also to mention several potential improvements, which could require some rtk-query changes

  1. the integration is implemented as middleware, which also listens to rtk-query actions. is it possible to get those action types somehow? for now I wrote them by hand - https://github.com/klis87/normy/blob/master/packages/normy-rtk-query/src/index.ts#L22 , but ofc it would be much better to reuse rtk-query types
  2. I could not manage to find a way to pass some meta attribute from query definition - like this - https://github.com/klis87/normy/blob/master/examples/rtk-query/src/api.js#L9 to the action here https://github.com/klis87/normy/blob/master/packages/normy-rtk-query/src/index.ts#L135 . This is problematic because without it I cannot allow an easy way to disable normalizations per specific queries and mutations. I added only global way as normalizeQuery and normalizeMutation options, but it is global, collocation style inside specific queries and mutations would be much better, like implemented in react-query addon - https://github.com/klis87/normy/tree/master/packages/normy-react-query#disabling-of-normalization-per-query-and-mutation-arrow_up
  3. This library uses structural sharing, so if it works like I think, after each refetch it is checked that data is different. it would be cool to have this information in actions, so that middleware could give up normalization for a refetch which did not update data, which is a waste as it will end up with normalization store exactly the same as it was. This would be very nice optimization, especially that rtk-query has features like refetch on refocus, which potentially could cause multiple refetches at the same time.
@markerikson
Copy link
Collaborator

Finally have a chance to look at this topic and think about it a bit.

I don't think we expose the executeQuery/executeMutation action types anywhere. Internally, those are part of the queryThunk and mutationThunk variables, and it doesn't look like those are included. I suppose in theory we could add those to api.internalActions, but also not sure that's something we ought to do.

Can you clarify what you mean by "disable normalization per specific queries"? It sounds like this addon works globally for all RTKQ endpoints and there's no way to isolate it?

I don't understand what you're asking for in regards to structural sharing. Can you clarify that question as well?

@klis87
Copy link
Author

klis87 commented Aug 11, 2024

I don't think we expose the executeQuery/executeMutation action types anywhere. Internally, those are part of the queryThunk and mutationThunk variables, and it doesn't look like those are included. I suppose in theory we could add those to api.internalActions, but also not sure that's something we ought to do.

If this is a problem, it is not a deal breaker, I was just forced to type rtk actions myself, and I will need to maintain them to make any updates myself as well. Should we do it? If we want to allow people to listen to those actions in middlewares, I think we should.

Can you clarify what you mean by "disable normalization per specific queries"? It sounds like this addon works globally for all RTKQ endpoints and there's no way to isolate it?

Please see how it is done for react-query - https://github.com/klis87/normy/tree/master/packages/normy-react-query#disabling-of-normalization-per-query-and-mutation-arrow_up

Generally you can:

  • enable normalization for all queries and mutations, and opt-out normalization for a given query and mutation
  • disable normalization for all queries and mutations, and opt-in normalization for a given query or mutation

About use case, you might have a very query with big data, and you know that this data will never be updated, then there is no point normalizing it, so you can disable it. Or, you have a mutation which you know should not update any data, but it receives a big payload, you might want to disable normalization for it to optimize performance, if needed.

I don't understand what you're asking for in regards to structural sharing. Can you clarify that question as well?

In normy core, I have this logic - https://github.com/klis87/normy/blob/master/packages/normy/src/create-normalizer.ts#L65 , which stops doing any update, if it is called with a data for a given query with the same reference as previous data.

It works with react-query, for example when this method is called here for instance - https://github.com/klis87/normy/blob/master/packages/normy-react-query/src/create-query-normalizer.ts#L64, it just works, I already have data with the same reference as previous query, if data has the same structure.

However, it does not work with rtk-query here - https://github.com/klis87/normy/blob/master/packages/normy-rtk-query/src/index.ts#L143 . Even if you refetch a query which gives you the same response, data is not referentially the same, so structural sharing does not work here. I suspect that rtk query applies structural sharing data transformation on a different level, and I cannot use it.

This is extreme optimization, as for example on refocus refetch, you can end up refetching dozens queries, which usually will not change data. With this feature, no normalization will be done for unchanged data,

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request rtk-query
Projects
None yet
Development

No branches or pull requests

2 participants