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

useRxData doesn't support findOne #45

Open
nirvdrum opened this issue Feb 7, 2022 · 2 comments
Open

useRxData doesn't support findOne #45

nirvdrum opened this issue Feb 7, 2022 · 2 comments

Comments

@nirvdrum
Copy link

nirvdrum commented Feb 7, 2022

I've run into a type definition error when providing useRxData with a query constructor that uses findOne. I think the issue is that findOne can return null, while find always returns a value, even if that value is an empty array. The TypeScript error isn't the clearest thing in the world:

TS2769: No overload matches this call.
  Overload 1 of 3, '(collectionName: string, queryConstructor: QueryConstructor<TodoChainDoc> | undefined): RxQueryResultDoc<TodoChainDoc>', gave the following error.
    Argument of type '(collection: RxCollection<TodoChainDoc>) => RxQuery<TodoChainDoc, RxDocument<TodoChainDoc, {}> | null>' is not assignable to parameter of type 'QueryConstructor<TodoChainDoc>'.
      Type 'RxQuery<TodoChainDoc, RxDocument<TodoChainDoc, {}> | null>' is not assignable to type 'RxQuery<TodoChainDoc, RxDocument<TodoChainDoc, {}>> | RxQuery<TodoChainDoc, RxDocument<TodoChainDoc, {}>[]> | undefined'.
        Type 'RxQuery<TodoChainDoc, RxDocument<TodoChainDoc, {}> | null>' is not assignable to type 'RxQuery<TodoChainDoc, RxDocument<TodoChainDoc, {}>>'.
          The types of '$.value' are incompatible between these types.
            Type 'RxDocument<TodoChainDoc, {}> | null' is not assignable to type 'RxDocument<TodoChainDoc, {}>'.
              Type 'null' is not assignable to type 'RxDocument<TodoChainDoc, {}>'.
  Overload 2 of 3, '(collectionName: string, queryConstructor: QueryConstructor<TodoChainDoc> | undefined, options?: Override<UseRxQueryOptions, { ...; }> | undefined): RxQueryResultDoc<...>', gave the following error.
    Argument of type '(collection: RxCollection<TodoChainDoc>) => RxQuery<TodoChainDoc, RxDocument<TodoChainDoc, {}> | null>' is not assignable to parameter of type 'QueryConstructor<TodoChainDoc>'.
  Overload 3 of 3, '(collectionName: string, queryConstructor: QueryConstructor<TodoChainDoc> | undefined, options?: Override<UseRxQueryOptions, { ...; }> | undefined): RxQueryResultJSON<...>', gave the following error.
    Argument of type '(collection: RxCollection<TodoChainDoc>) => RxQuery<TodoChainDoc, RxDocument<TodoChainDoc, {}> | null>' is not assignable to parameter of type 'QueryConstructor<TodoChainDoc>'.

I can manually query against the collection or just use find and unwrap the array in the meanwhile. Please let me know if I can be of any assistance. I couldn't see a simple way to change the return type based on using find vs findOne and I don't want to break code on existing users by forcing null as a potential return value on all queries. Maybe the solution is a new hook (e.g, useRxDataOne)?

@cvara
Copy link
Owner

cvara commented Feb 12, 2022

Hey @nirvdrum. Can you please provide a concrete example? Also which versions of rxdb-hooks/rxdb are you using?

@nirvdrum
Copy link
Author

nirvdrum commented Feb 13, 2022

Hi @cvara. Thanks for taking a look. I'm using rxdb-hooks 4.0.1.

What I was trying to do was:

const todosQuery = (collection: any) => {
    collection.findByIds(todoChain.todo_ids)
};
const { result: todoMap, isFetching } = useRxData('todos', todosQuery);

Generally I use type annotations so I don't get back a generic RxDocument or RxCollection, but I couldn't find a signature that would work. So, here I'm just using the any type and letting the type inference engine handle things up to the useRxData call. The TypeScript error I received was:

TS2769: No overload matches this call.
  Overload 1 of 3, '(collectionName: string, queryConstructor: QueryConstructor<unknown> | undefined): RxQueryResultDoc<unknown>', gave the following error.
    Argument of type '(collection: any) => void' is not assignable to parameter of type 'QueryConstructor<unknown>'.
      Type 'void' is not assignable to type 'RxQuery<unknown, RxDocumentBase<unknown, {}>> | RxQuery<unknown, RxDocumentBase<unknown, {}>[]> | undefined'.
  Overload 2 of 3, '(collectionName: string, queryConstructor: QueryConstructor<unknown> | undefined, options?: Override<UseRxQueryOptions, { json?: false | undefined; }> | undefined): RxQueryResultDoc<...>', gave the following error.
    Argument of type '(collection: any) => void' is not assignable to parameter of type 'QueryConstructor<unknown>'.
  Overload 3 of 3, '(collectionName: string, queryConstructor: QueryConstructor<unknown> | undefined, options?: Override<UseRxQueryOptions, { json: true; }> | undefined): RxQueryResultJSON<...>', gave the following error.
    Argument of type '(collection: any) => void' is not assignable to parameter of type 'QueryConstructor<unknown>'.

What I've ended up doing is:

const todosCollection = useRxCollection<TodoDoc>('todos');

useEffect(() => {
  const subscription = todosCollection?.findByIds$(todoIds).subscribe((todos) => {
      // todos is an ES6 Map<string, TodoDocument>.
      console.log("todo map", todos.get("some_id"));
  });

  return () => subscription?.unsubscribe();
}, [todoIds, todosCollection]);

While this works, I really like how rxdb-hooks handles all of the annoying subscribe and unsubscribe logic along with return any "loading" state.

Please let me know if you need anymore info.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants