Skip to content

Bug: Eslint hooks returned by factory functions not linted #25065

@KATT

Description

@KATT

React version: *

Steps To Reproduce

See my draft PR with failing tests 👉 #25066.

Given the following code:

// Factory function for creating hooks
function createHooks() {
  return {
    foo: {
      useQuery: () => {
        data: 'foo.useQuery'
      },
    }
  };
}
const hooks = createHooks();

export const MyComponent = () => {
  if (Math.random() < 0.5) {
    return null;
  }
  // ❌ This should fail the linter
  const query = hooks.foo.useQuery();

  return <>{query.data}</>;
}

The current behavior

The linting does not catch that the hooks.foo.useQuery() is used conditionally.

The expected behavior

The linting should catch that the hooks.foo.useQuery() is used conditionally.

Failing tests / link to code

See my draft PR with failing tests 👉 #25066.

I've highlighted areas and things that are up for discussions around this.

Additional context

Partial workaround

If the object returned is not a deep getter, it's possible to PascalCase it and do it like this:

// Factory function for creating hooks
function createHooks() {
  return {
    useFoo: () => {
      data: 'foo.useQuery'
  };
}
const Hooks = createHooks();

export const MyComponent = () => {
  if (Math.random() < 0.5) {
    return null;
  }
  // ✅ This will fail the linter
  const query = Hooks.useFoo();

  return <>{query.data}</>;
}

It's okay if hooks can be called outside of React-components

#25065 (comment)

Background

I'm the creator of tRPC where we use the following pattern for users to create the root hooks:

// Initialization of the typesafe tRPC hooks
export const trpc = createReactQueryHooks<AppRouter>();

// MyComponent.tsx
export function MyComponent() {
  const query = trpc.useQuery(['post.byId', { id: '1' }])

  return <pre>{JSON.stringify(query.data ?? null, null, 4)}</pre>
}

In the coming version of tRPC, we are planning on have an API that looks like the below, which also won't be caught.

export function MyComponent() {
  const query = trpc.post.byId.useQury({ id: '1'});

  return <pre>{JSON.stringify(query.data ?? null, null, 4)}</pre>
}

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions