---
title: "React Query — enabled: !!value Silent Skip on Empty String"
aliases: [react-query-enabled, react-query-silent-skip, usequery-disabled]
tags: [react, react-query, frontend, debugging, gotcha, javascript]
sources:
  - "daily/2026-04-30.md"
created: 2026-04-30
updated: 2026-04-30
---

# React Query — `enabled: !!value` Silent Skip on Empty String

When a React Query hook uses `enabled: !!someId` as a condition to fire the request, passing an empty string `""` as `someId` silently disables the query — `!!""` is `false`. The query never fires, the loading state resolves immediately with `undefined` data, and the UI shows nothing without any error or console warning.

## Key Points

- **`!!""` is `false`** — empty string is falsy in JavaScript; React Query treats it as "disabled"
- **Symptom:** component renders, no network request is made, data is `undefined` — looks like an API error but there is no request at all
- **Diagnosis:** in React Query DevTools or browser network tab — if there's no request for a query that should have fired, check `enabled` condition for falsy values
- **Fix option A:** use a separate hook or endpoint that doesn't require the ID (e.g., `GET /clients/all-projects` that returns all projects without a client filter)
- **Fix option B:** use `enabled: someId !== null && someId !== undefined` instead of `enabled: !!someId` to allow empty-string IDs

## Details

### The Failure Pattern

```typescript
// useProjects hook — requires clientId
const { data: projects } = useQuery(
  ["projects", clientId],
  () => fetchProjects(clientId),
  { enabled: !!clientId }   // ← silently disabled when clientId === ""
);

// In a form where the user hasn't selected a client yet:
const [clientId, setClientId] = useState("");  // empty string default
// → query never fires, projects is undefined, dropdown is empty
```

### Fix A: Separate "All Projects" Endpoint

When the UI needs ALL projects regardless of client selection, create a separate endpoint and hook that doesn't require a `clientId`:

```typescript
// New hook — no clientId required
export function useAllProjects() {
  return useQuery(["projects", "all"], fetchAllProjects);  // always enabled
}

// New backend endpoint
// GET /clients/all-projects → returns all projects user has access to
```

This avoids changing the `enabled` logic and makes the "fetch all" intent explicit.

### Fix B: Explicit Null Check

When the ID is legitimately optional but not always empty string:

```typescript
const { data: projects } = useQuery(
  ["projects", clientId],
  () => fetchProjects(clientId),
  { enabled: clientId !== null && clientId !== undefined }
  // now "" (empty string) is allowed and the query fires
);
```

### Common Falsy Values to Watch For in `enabled`

| Value | `!!value` | Often means |
|-------|-----------|-------------|
| `""` | `false` | Default state, unselected dropdown |
| `0` | `false` | First item in a zero-indexed list |
| `null` | `false` | Not yet loaded |
| `undefined` | `false` | Not yet loaded |
| `"0"` | `true` (string!) | String zero — may be surprising |

When in doubt, use `enabled: value !== null && value !== undefined` rather than `enabled: !!value`.

## Related Concepts

- [[wiki/concepts/zustand-async-hydration]] — another silent timing bug in React where state isn't ready when components mount
- [[wiki/tech-patterns/react-vite-typescript]] — React patterns in Oliver projects

## Sources

- [[daily/2026-04-30.md]] — Brief form: projects dropdown empty because `useProjects('')` was disabled by `enabled: !!clientId`; fixed with `useAllProjects()` hook + `GET /clients/all-projects` endpoint
