TanStack / query

🤖 Powerful asynchronous state management, server-state utilities and data fetching for the web. TS/JS, React Query, Solid Query, Svelte Query and Vue Query.
https://tanstack.com/query
MIT License
40.54k stars 2.73k forks source link

feat(solid-query): Solid Query Adapter for TanStack Query #4211

Closed lukesmurray closed 1 year ago

lukesmurray commented 1 year ago

This pull request aims to add the TanStack Query adapter for Solid JS. This pull request will add the following key primitives to the package.

The adapter docs have been updated as well as examples have been added.

Acknowledgments

The work on solid-query would not have been possible without

This is a follow-up to #4195 but rebased on main and with commits from beta removed per discussion with @TkDodo and @ardeora.

lukesmurray commented 1 year ago

Before this is merged @ardeora has some follow up work that is not included. So please hold off until we have it.

codesandbox-ci[bot] commented 1 year ago

This pull request is automatically built and testable in CodeSandbox.

To see build info of the built libraries, click here or the icon next to each commit SHA.

Latest deployment of this branch, based on commit de90e6bf9a4381b6994e7ac2061cd6e5e5346f89:

Sandbox Source
@tanstack/query-example-react-basic Configuration
@tanstack/query-example-react-basic-typescript Configuration
@tanstack/query-example-solid-basic-typescript Configuration
ardeora commented 1 year ago

🚨 one thing we need to do to make the publish script work is to add solid-query to the package list here (at the end I think):

https://github.com/TanStack/query/blob/357ec041a6fcc4a550f3df02c12ecc7bcdefbc05/scripts/config.ts#L5

Thank you! I added solid-query to the packages in the list below

ardeora commented 1 year ago

let's also add one example to .codesandbox/ci.json so that we can see a preview build of solid-query on each PR:

https://github.com/TanStack/query/blob/357ec041a6fcc4a550f3df02c12ecc7bcdefbc05/.codesandbox/ci.json#L3

Yep! I added the typescript example and it's working great here https://codesandbox.io/s/tanstack-query-example-solid-basic-typescript-lhsczt

ardeora commented 1 year ago

Alright I think we should be good to go here. All the tests seem to be passing. And I applied the batching state updates which works great now. Thanks for all the feedback here 😄

TkDodo commented 1 year ago

exciting 🚀

aulneau commented 1 year ago

just wanted to pop in and say great work, this is so exciting!

lukesmurray commented 1 year ago

Ok everything seems to be ready to go. @TkDodo feel free to merge. Please add @ardeora, @lukesmurray, @jennyckaplan, and @oscartbeaumont as co-authors on the final merge if possible. This was a team effort, led by @ardeora and I would love to see everyone get recognition for their contributions here.

Cheers 🍻

codecov-commenter commented 1 year ago

Codecov Report

Base: 96.36% // Head: 96.57% // Increases project coverage by +0.21% :tada:

Coverage data is based on head (de90e6b) compared to base (eab6e2c). Patch has no changes to coverable lines.

Additional details and impacted files ```diff @@ Coverage Diff @@ ## main #4211 +/- ## ========================================== + Coverage 96.36% 96.57% +0.21% ========================================== Files 45 72 +27 Lines 2281 2949 +668 Branches 640 814 +174 ========================================== + Hits 2198 2848 +650 - Misses 80 99 +19 + Partials 3 2 -1 ``` | [Impacted Files](https://codecov.io/gh/TanStack/query/pull/4211?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None) | Coverage Δ | | |---|---|---| | [src/core/utils.ts](https://codecov.io/gh/TanStack/query/pull/4211/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None#diff-c3JjL2NvcmUvdXRpbHMudHM=) | | | | [src/devtools/tests/utils.tsx](https://codecov.io/gh/TanStack/query/pull/4211/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None#diff-c3JjL2RldnRvb2xzL3Rlc3RzL3V0aWxzLnRzeA==) | | | | [src/core/mutationObserver.ts](https://codecov.io/gh/TanStack/query/pull/4211/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None#diff-c3JjL2NvcmUvbXV0YXRpb25PYnNlcnZlci50cw==) | | | | [src/react/useQuery.ts](https://codecov.io/gh/TanStack/query/pull/4211/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None#diff-c3JjL3JlYWN0L3VzZVF1ZXJ5LnRz) | | | | [src/react/utils.ts](https://codecov.io/gh/TanStack/query/pull/4211/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None#diff-c3JjL3JlYWN0L3V0aWxzLnRz) | | | | [src/react/Hydrate.tsx](https://codecov.io/gh/TanStack/query/pull/4211/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None#diff-c3JjL3JlYWN0L0h5ZHJhdGUudHN4) | | | | [src/react/QueryErrorResetBoundary.tsx](https://codecov.io/gh/TanStack/query/pull/4211/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None#diff-c3JjL3JlYWN0L1F1ZXJ5RXJyb3JSZXNldEJvdW5kYXJ5LnRzeA==) | | | | [src/devtools/devtools.tsx](https://codecov.io/gh/TanStack/query/pull/4211/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None#diff-c3JjL2RldnRvb2xzL2RldnRvb2xzLnRzeA==) | | | | [src/core/mutation.ts](https://codecov.io/gh/TanStack/query/pull/4211/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None#diff-c3JjL2NvcmUvbXV0YXRpb24udHM=) | | | | [src/core/mutationCache.ts](https://codecov.io/gh/TanStack/query/pull/4211/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None#diff-c3JjL2NvcmUvbXV0YXRpb25DYWNoZS50cw==) | | | | ... and [107 more](https://codecov.io/gh/TanStack/query/pull/4211/diff?src=pr&el=tree-more&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None) | | Help us with your feedback. Take ten seconds to tell us [how you rate us](https://about.codecov.io/nps?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None). Have a feature suggestion? [Share it here.](https://app.codecov.io/gh/feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None)

:umbrella: View full report at Codecov.
:loudspeaker: Do you have feedback about the report comment? Let us know in this issue.

TkDodo commented 1 year ago

I was just about to merge this when I took another look at the codesandbox preview build, and it sadly doesn't render anymore:

https://codesandbox.io/s/tanstack-query-example-solid-basic-typescript-17fbsy

The error is:

Uncaught ReferenceError: React is not defined
    at QueryClientProvider (QueryClientProvider.jsx:37:5)
    at dev.js:519:12
    at untrack (dev.js:425:12)
    at Object.fn (dev.js:515:37)
    at runComputation (dev.js:695:22)
    at updateComputation (dev.js:680:3)
    at devComponent (dev.js:526:3)
    at createComponent (dev.js:1228:10)
    at App (index.tsx:142:3)
    at dev.js:519:12

I was working yesterday for sure :/

OrJDev commented 1 year ago

I was just about to merge this when I took another look at the codesandbox preview build, and it sadly doesn't render anymore:

https://codesandbox.io/s/tanstack-query-example-solid-basic-typescript-17fbsy

The error is:

Uncaught ReferenceError: React is not defined
    at QueryClientProvider (QueryClientProvider.jsx:37:5)
    at dev.js:519:12
    at untrack (dev.js:425:12)
    at Object.fn (dev.js:515:37)
    at runComputation (dev.js:695:22)
    at updateComputation (dev.js:680:3)
    at devComponent (dev.js:526:3)
    at createComponent (dev.js:1228:10)
    at App (index.tsx:142:3)
    at dev.js:519:12

I was working yesterday for sure :/

same things here, it does work tho when using @adeora/solid-query instead of @tanstack/solid-query

TkDodo commented 1 year ago

Yes, we are seeing this, too. This seems to be an upstream problem with vite-plugin-solid.

It worked with 2.3.6 but broke with 2.3.7 which was released today.

we actually pinned the plugin version because of this in our official example, which is working:

https://codesandbox.io/s/github/tanstack/query/tree/main/examples/solid/simple?file=/package.json:411-443

TkDodo commented 1 year ago

upstream issue:

ardeora commented 1 year ago

I was just about to merge this when I took another look at the codesandbox preview build, and it sadly doesn't render anymore: https://codesandbox.io/s/tanstack-query-example-solid-basic-typescript-17fbsy The error is:

Uncaught ReferenceError: React is not defined
    at QueryClientProvider (QueryClientProvider.jsx:37:5)
    at dev.js:519:12
    at untrack (dev.js:425:12)
    at Object.fn (dev.js:515:37)
    at runComputation (dev.js:695:22)
    at updateComputation (dev.js:680:3)
    at devComponent (dev.js:526:3)
    at createComponent (dev.js:1228:10)
    at App (index.tsx:142:3)
    at dev.js:519:12

I was working yesterday for sure :/

same things here, it does work tho when using @adeora/solid-query instead of @tanstack/solid-query

Yeah this was an issue with vite-plugin-solid that we just recently resolved. Can you upgrade vite-plugin-solid to v2.3.8?

https://stackblitz.com/edit/vitejs-vite-csdjj1?file=package.json,src%2Fmain.tsx,src%2FApp.tsx

Here is a working stackblitz sandbox for reference

OrJDev commented 1 year ago

I was just about to merge this when I took another look at the codesandbox preview build, and it sadly doesn't render anymore: https://codesandbox.io/s/tanstack-query-example-solid-basic-typescript-17fbsy The error is:

Uncaught ReferenceError: React is not defined
    at QueryClientProvider (QueryClientProvider.jsx:37:5)
    at dev.js:519:12
    at untrack (dev.js:425:12)
    at Object.fn (dev.js:515:37)
    at runComputation (dev.js:695:22)
    at updateComputation (dev.js:680:3)
    at devComponent (dev.js:526:3)
    at createComponent (dev.js:1228:10)
    at App (index.tsx:142:3)
    at dev.js:519:12

I was working yesterday for sure :/

same things here, it does work tho when using @adeora/solid-query instead of @tanstack/solid-query

Yeah this was an issue with vite-plugin-solid that we just recently resolved. Can you upgrade vite-plugin-solid to v2.3.8?

https://stackblitz.com/edit/vitejs-vite-csdjj1?file=package.json,src%2Fmain.tsx,src%2FApp.tsx

Here is a working stackblitz sandbox for reference

Yes it is ok i managed to get it working and added it as an addon to Create JD App,

great work you did there.

ardeora commented 1 year ago

@all-contributors please add @lukesmurray for code.

ardeora commented 1 year ago

@all-contributors please add @jennyckaplan for code.

allcontributors[bot] commented 1 year ago

@ardeora

I've put up a pull request to add @jennyckaplan! :tada:

ardeora commented 1 year ago

@all-contributors please add @oscartbeaumont for code.

allcontributors[bot] commented 1 year ago

@ardeora

I've put up a pull request to add @oscartbeaumont! :tada:

vyktoremario commented 1 year ago

Why does this break for every patch version of vite-plugin-solid? It seems as if 2.3.9 which is the latest version is causing the same error as above.

lukesmurray commented 1 year ago

I'm not sure, and I'm sorry you're having that issue. I suggest posting an issue to vite-plugin-solid with some information about the error you're getting. If you're getting an error, it's likely other packages are getting errors as well, and my guess is it is an upstream issue rather than a problem with solid-query. But if you suspect it is an issue with solid-query feel free to open an issue with some more information about the error in this repo, and we will take a look.

milahu commented 1 year ago

why invent new names for the API?

edit: because react is wrong and solid is right. solid also has createSignal, createEffect, ...

react-query solid-query
useQuery createQuery
useBaseQuery createBaseQuery
useQueries createQueries
useQueryClient useQueryClient
useHydrate (missing)
useQueryErrorResetBoundary (missing)
useIsFetching useIsFetching
useMutation createMutation
useInfiniteQuery createInfiniteQuery
result state
milahu commented 1 year ago

@tanstack/solid-query-persist-client draft

because caching + persistence = profit

```jsx /* @tanstack/solid-query-persist-client usage this is a drop-in replacement for QueryClientProvider from @tanstack/solid-query function App() { return (
) } see also https://tanstack.com/query/v4/docs/plugins/persistQueryClient#persistqueryclientprovider based on QueryClientProvider in node_modules/@tanstack/solid-query/build/lib/QueryClientProvider.esm.js node_modules/@tanstack/solid-query/build/solid/QueryClientProvider.jsx PersistQueryClientProvider in node_modules/@tanstack/react-query-persist-client/build/lib/PersistQueryClientProvider.esm.js persistQueryClientSubscribe in node_modules/@tanstack/query-persist-client-core/build/lib/persist.esm.js */ import { createContext, mergeProps, onMount, onCleanup } from 'solid-js'; import { persistQueryClientSubscribe } from "@tanstack/query-persist-client-core" import { defaultContext } from "@tanstack/solid-query" // TODO? // export { persistQueryClient, persistQueryClientRestore, persistQueryClientSave, persistQueryClientSubscribe } // export { removeOldestQuery } //export * from '@tanstack/query-persist-client-core'; const QueryClientSharingContext = createContext(false); // If we are given a context, we will use it. // Otherwise, if contextSharing is on, we share the first and at least one // instance of the context across the window // to ensure that if Solid Query is used across // different bundles or microfrontends they will // all use the same **instance** of context, regardless // of module scoping. function getQueryClientContext(context, contextSharing) { if (context) { return context; } if (contextSharing && typeof window !== 'undefined') { if (!window.SolidQueryClientContext) { window.SolidQueryClientContext = defaultContext; } return window.SolidQueryClientContext; } return defaultContext; } export const PersistQueryClientProvider = (props) => { const mergedProps = mergeProps({ contextSharing: false, }, props); let persistQueryClientUnsubscribe onMount(() => { // same as in non-persisted provider //console.log('PersistQueryClientProvider.onMount: mount') mergedProps.client.mount() // persistence ... // note: different API // persistQueryClientSubscribe: props.queryClient // QueryClientProvider: props.client mergedProps.queryClient = mergedProps.client // subscribe //console.log('PersistQueryClientProvider.onMount: subscribe') persistQueryClientUnsubscribe = persistQueryClientSubscribe(mergedProps) // test: mount later //mergedProps.client.mount() }); onCleanup(() => { // same as in non-persisted provider //console.log('PersistQueryClientProvider.onCleanup: unmount') mergedProps.client.unmount() // persistence ... //console.log('PersistQueryClientProvider.onCleanup: unsubscribe') // unsubscribe persistQueryClientUnsubscribe() }) const QueryClientContext = getQueryClientContext(mergedProps.context, mergedProps.contextSharing); return ( {mergedProps.children} ); }; ```

next challenge:

DOMException: Failed to execute 'put' on 'IDBObjectStore': [object Array] could not be cloned.

https://github.com/localForage/localForage/issues/610

if the object contains a function it can't be stored inside a database

with indexeddb persister from https://tanstack.com/query/v4/docs/plugins/persistQueryClient#building-a-persister

problem: queryKey is a solidjs proxy object

queryClient.clientState.queries[i].queryKey

https://tanstack.com/query/v4/docs/adapters/solid-query#important-differences-between-solid-query--react-query

// ❌ react version
const queryKey = ["todos", todo]
useQuery(queryKey, fetchTodos)

// ✅ solid version
const queryKey = ["todos", todo()]
const getQueryKey = () => queryKey
createQuery(getQueryKey, fetchTodos)

this looks like a good place to cleanup the queryKey

@tanstack/solid-query/build/solid/createBaseQuery.js

    // NOTE(milahu): this is reactive to options
    createComputed(() => {
        const newDefaultedOptions = queryClient.defaultQueryOptions(options);
        // TODO(milahu): cleanup options?
        observer.setOptions(newDefaultedOptions);
    });

indexeddb persister

related: https://github.com/faassen/solid-dexie

related: withCacheStorage in @solid-primitives/fetch

lukesmurray commented 1 year ago

Thank you for the comments @milahu. You figured out the naming logic before I had a chance to reply!

With regard to the missing apis.

About your error, you may want to use unwrap to get the store without a proxy.

About your proposal for the query key. I'm not quite sure if it would work. It depends on what todo is. But if todo is a signal, you're resolving the signal outside of getQueryKey so getQueryKey would not be reactive.

// only runs once
const queryKey = ["todos", todo()]

// runs multiple times but returns the non-reactive array every time
const getQueryKey = () => queryKey

In general, if you use query key factories the fact that query keys are functions can be abstracted away fairly easily and that's probably the approach I would recommend.