QwikDev / QwikDev/qwik

[🐞] useTask, useVisibleTask runs even if the component is not returned in layout.tsx

Open
#8,782 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug runtime
Dominant language
TypeScript
Stars
22.1k
Forks
1.4k
Avg merge
1d 10h
Merged PRs (30d)
52

Description

Which component is affected?

Qwik Runtime

Describe the bug

Qwik with Qwik City layout.tsx has issues with useTask, useVisibleTask .

Reproduction

https://stackblitz.com/edit/vitejs-vite-5mrs5yau?file=src%2Froutes%2Findex.tsx

Steps to reproduce
Project setup
src/
- contexts.ts
- root.tsx
- routes/
  - index.tsx
  - layout.tsx

contexts.ts

import { Signal, createContextId } from '@builder.io/qwik';

export const LoadingContext =  createContextId<Signal<boolean>>('app.LoadingContext');
export const SomeContext = createContextId<Signal<boolean>>('app.SomeContext');

root.tsx

  const loading = useSignal(true);
  useContextProvider(LoadingContext, loading);

  const someData = useSignal(false);
  useContextProvider(SomeContext, someData);

  useVisibleTask$(async () => {
    console.log('Loading...');

    someData.value = true;
    await new Promise((resolve) => setTimeout(resolve, 500));

    loading.value = false;
    console.log('Loading done');
  });

  return (
    <QwikCityProvider>
      <head>
        <meta charset="utf-8" />
        {!isDev && (
          <link
            rel="manifest"
            href={`${import.meta.env.BASE_URL}manifest.json`}
          />
        )}
        <RouterHead />
      </head>
      <body lang="en">
        <RouterOutlet />
      </body>
    </QwikCityProvider>
  );

layout.tsx

import { component$, Slot, useContext } from '@builder.io/qwik';
import { LoadingContext } from '~/contexts';

export default component$(() => {
  const loading = useContext(LoadingContext);

  if (loading.value) {
    return <div>Loading...</div>;
  }

  return <Slot />;
});
Issue 1

index.tsx

import { component$, useTask$, useVisibleTask$ } from '@builder.io/qwik';

const NestedComp = component$(() => {
  useTask$(() => {
    console.log('Component useTask: NestedComp');
  });

  useVisibleTask$(() => {
    console.log('Component useVisibleTask: NestedComp');
  });

  return <div>NestedComp</div>;
});

export default component$(() => {
  useTask$(() => {
    console.log('Component useTask: index');
  });

  useVisibleTask$(() => {
    console.log('Component useVisibleTask: index');
  });

  return (
    <>
      <NestedComp />
    </>
  );
});

expected console output:

Loading...
Loading done
Component useVisibleTask: index
Component useVisibleTask: NestedComp

current console output:

Loading...
Component useVisibleTask: index
Loading done
Component useVisibleTask: NestedComp
Issue 1 (with a content in the index.tsx component)

index.tsx

import { component$, useTask$, useVisibleTask$ } from '@builder.io/qwik';

const NestedComp = component$(() => {
  useTask$(() => {
    console.log('Component useTask: NestedComp');
  });

  useVisibleTask$(() => {
    console.log('Component useVisibleTask: NestedComp');
  });

  return <div>NestedComp</div>;
});

export default component$(() => {
  useTask$(() => {
    console.log('Component useTask: index');
  });

  useVisibleTask$(() => {
    console.log('Component useVisibleTask: index');
  });

  return (
    <>
      <div>Hello</div>
      <NestedComp />
    </>
  );
});

current == expected console output:

Loading...
Loading done
Component useVisibleTask: index
Component useVisibleTask: NestedComp
Issue 2

Conditional rendering on NestedComp

index.tsx

import {
  component$,
  useContext,
  useTask$,
  useVisibleTask$,
} from '@builder.io/qwik';
import { SomeContext } from '~/contexts';

const NestedComp = component$(() => {
  useTask$(() => {
    console.log('Component useTask: NestedComp');
  });

  useVisibleTask$(() => {
    console.log('Component useVisibleTask: NestedComp');
  });

  return <div>NestedComp</div>;
});

export default component$(() => {
  const someData = useContext(SomeContext);

  useTask$(() => {
    console.log('Component useTask: index');
  });

  useVisibleTask$(() => {
    console.log('Component useVisibleTask: index');
  });

  return <>{someData.value && <NestedComp />}</>;
});

expected console output:

Loading...
Loading done
Component useVisibleTask: index
Component useTask: NestedComp
Component useVisibleTask: NestedComp

current console output:

Loading...
Component useVisibleTask: index
Component useTask: NestedComp
Component useVisibleTask: NestedComp
Loading done
Issue 2 (with a content in the index.tsx component)

index.tsx

import {
  component$,
  useContext,
  useTask$,
  useVisibleTask$,
} from '@builder.io/qwik';
import { SomeContext } from '~/contexts';

const NestedComp = component$(() => {
  useTask$(() => {
    console.log('Component useTask: NestedComp');
  });

  useVisibleTask$(() => {
    console.log('Component useVisibleTask: NestedComp');
  });

  return <div>NestedComp</div>;
});

export default component$(() => {
  const someData = useContext(SomeContext);

  useTask$(() => {
    console.log('Component useTask: index');
  });

  useVisibleTask$(() => {
    console.log('Component useVisibleTask: index');
  });

  return (
    <>
      <div>Hello</div>
      {someData.value && <NestedComp />}
    </>
  );
});

expected console output:

Loading...
Loading done
Component useVisibleTask: index
Component useTask: NestedComp
Component useVisibleTask: NestedComp

current console output:

Loading...
Component useTask: NestedComp
Component useVisibleTask: NestedComp
Loading done
Component useVisibleTask: index
System Info
Stackblitz
  System:
    OS: Linux 5.0 undefined
    CPU: (8) x64 Intel(R) Core(TM) i9-9880H CPU @ 2.30GHz
    Memory: 0 Bytes / 0 Bytes
    Shell: 1.0 - /bin/jsh
  Binaries:
    Node: 22.22.3 - /usr/local/bin/node
    Yarn: 1.22.19 - /usr/local/bin/yarn
    npm: 10.8.2 - /usr/local/bin/npm
    pnpm: 8.15.6 - /usr/local/bin/pnpm
  npmPackages:
    @builder.io/qwik: ^1.20.0 => 1.20.0 
    @builder.io/qwik-city: ^1.20.0 => 1.20.0 
    typescript: 5.4.5 => 5.4.5 
    undici: * => 8.5.0 
    vite: 7.3.1 => 7.3.1 

My PC
  System:
    OS: Windows 11 10.0.26200
    CPU: (20) x64 12th Gen Intel(R) Core(TM) i7-12700K
    Memory: 3.54 GB / 15.76 GB
  Binaries:
    Node: 26.4.0 - C:\Users\doong\apps\nodejs\node.EXE
    npm: 11.17.0 - C:\Users\doong\apps\nodejs\npm.CMD
    pnpm: 11.9.0 - C:\Users\doong\AppData\Local\pnpm\bin\pnpm.CMD
    Deno: 2.9.0 - C:\Users\doong\.deno\bin\deno.EXE
  Browsers:
    Chrome: 149.0.7827.201
    Edge: Chromium (149.0.4022.98)
    Firefox: 152.0.3 - C:\Program Files\Mozilla Firefox\firefox.exe
    Internet Explorer: 11.0.26100.8115
  npmPackages:
    @builder.io/qwik: ^1.20.0 => 1.20.0 
    @builder.io/qwik-city: ^1.20.0 => 1.20.0 
    typescript: 5.4.5 => 5.4.5 
    undici: ^8.5.0 => 8.5.0
    vite: 7.3.1 => 7.3.1
Additional Information

No response

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the linked StackBlitz reproduction and the shown root.tsx, routes/layout.tsx, and routes/index.tsx files; compare hook execution when the layout returns Loading... versus Slot. Trace Qwik Runtime scheduling for useTask$ and useVisibleTask$ with conditional NestedComp rendering, and verify that the observed output matches the expected ordering.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
frontend, web-dev
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.