Skip to content

Commit

Permalink
refactor: rename useBrowserVisibleTask to useVisibleTask (QwikDev#3215)
Browse files Browse the repository at this point in the history
* refactor: rename useBrowserVisibleTask to useVisibleTask

* ๐Ÿพ

* ๐Ÿž
  • Loading branch information
manucorporat authored Mar 1, 2023
1 parent 14e7fae commit fc078e5
Show file tree
Hide file tree
Showing 30 changed files with 111 additions and 92 deletions.
4 changes: 2 additions & 2 deletions .vscode/qwik.code-snippets
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,9 @@
"useBrowserVisibleTask": {
"scope": "javascriptreact,typescriptreact",
"prefix": "q:useBrowserVisibleTask",
"description": "useBrowserVisibleTask$() function hook",
"description": "useVisibleTask$() function hook",
"body": [
"useBrowserVisibleTask$(({ track }) => {",
"useVisibleTask$(({ track }) => {",
" $0",
"});",
""
Expand Down
28 changes: 14 additions & 14 deletions packages/docs/src/routes/docs/components/lifecycle/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ Thanks to [Resumability](/docs/concepts/resumable/index.mdx), components life an
- `VisibleTask` - runs after `Render` and when the component becomes visible

```
useTask$ ------> RENDER -----> useBrowserVisibleTask$
useTask$ ------> RENDER -----> useVisibleTask$
|
| --- SERVER or BROWSER --- | ----- BROWSER ----- |
|
Expand All @@ -29,12 +29,12 @@ Thanks to [Resumability](/docs/concepts/resumable/index.mdx), components life an

**SERVER**: Usually **the life of a component starts on the server** (during SSR or SSG), in that case, the `useTask$` and `RENDER` will run in the server, and then the `VisibleTask` will run in the browser, after the component is visible.

> **Notice** that because the component was mounted in the server, **only useBrowserVisibleTask$() runs in the browser**. This is because the browser continues the same lifecycle, that was paused in the server right after the render and resumed in the browser.
> **Notice** that because the component was mounted in the server, **only useVisibleTask$() runs in the browser**. This is because the browser continues the same lifecycle, that was paused in the server right after the render and resumed in the browser.
**BROWSER**: Sometimes a component will be first mounted/rendered in the browser, for example when the user SPA navigates to a new page, or a "modal" component first appears in the page. In that case, the lifecycle will run like this:

```
useTask$ --> RENDER --> useBrowserVisibleTask$
useTask$ --> RENDER --> useVisibleTask$
| ---------------- BROWSER --------------- |
```
Expand Down Expand Up @@ -104,13 +104,13 @@ export const Cmp = component$(() => {

The example above uses the `track` function to watch changes in `() => count.value`. The callback will run once in the SSR when the component is mounted and every time `count.value` changes.

> Notice that `useTask$()` runs **BEFORE** the actual rendering and in the server, so if you need to do any DOM manipulation, use `useBrowserVisibleTask$()` instead, which runs on the client after rendering.
> Notice that `useTask$()` runs **BEFORE** the actual rendering and in the server, so if you need to do any DOM manipulation, use `useVisibleTask$()` instead, which runs on the client after rendering.
### Use `useTask$()` when you need to

- Run async tasks before rendering
- Run code only once before component is first rendered
- Compute derived state from tracked state (without causing potential re-rendering like in `useBrowserVisibleTask$`)
- Compute derived state from tracked state (without causing potential re-rendering like in `useVisibleTask$`)
- Programmatically run code when state changes

> Note, if you're thinking about load data (like using `fetch()`) inside of `useTask$`, consider using [`useResource$()`](/docs/components/resource/index.mdx) instead. This API is more efficient in terms of leveraging SSR streaming and parallel data fetching.
Expand Down Expand Up @@ -147,28 +147,28 @@ export const Cmp = component$(() => {

> But as mentioned above - for data fetching, consider using [`useResource$()`](/docs/components/resource/index.mdx) instead.
## `useBrowserVisibleTask$()`
## `useVisibleTask$()`

- **When:** once the component becomes visible on the browser, and when tracked state changes
- **Times:** at least once
- **Platform:** browser only

`useBrowserVisibleTask$()` registers a hook to be executed when the component becomes visible in the viewport, it will run at least once in the browser, and it can be reactive and re-execute when some **tracked** [signal or store](/docs/components/state/index.mdx) changes, like this:
`useVisibleTask$()` registers a hook to be executed when the component becomes visible in the viewport, it will run at least once in the browser, and it can be reactive and re-execute when some **tracked** [signal or store](/docs/components/state/index.mdx) changes, like this:

```tsx
useBrowserVisibleTask$(({ track }) => {
useVisibleTask$(({ track }) => {
track(() => store.count);
// will run when the component becomes visible and every time "store.count" changes
console.log('runs in the browser');
});
```

Under the hood, `useBrowserVisibleTask$()` creates a DOM listener that uses [Intersection Observer](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API) to detect when the component becomes visible in the viewport.
Under the hood, `useVisibleTask$()` creates a DOM listener that uses [Intersection Observer](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API) to detect when the component becomes visible in the viewport.

However this `strategy` can be changed, and for example, run when the `document` is ready.

```tsx
useBrowserVisibleTask$(() => console.log('runs in the browser'), {
useVisibleTask$(() => console.log('runs in the browser'), {
strategy: 'document-ready', // 'load' | 'visible' | 'idle'
});
```
Expand All @@ -184,7 +184,7 @@ This is a unique feature of Qwik, any other frameworks would execute this and ot
```tsx
export const Timer = component$(() => {
const count = useSignal(0);
useBrowserVisibleTask$(() => {
useVisibleTask$(() => {
// Only runs in the client
const timer = setInterval(() => {
count.value++;
Expand All @@ -197,11 +197,11 @@ export const Timer = component$(() => {
});
```

### When to use `useBrowserVisibleTask$()`
### When to use `useVisibleTask$()`

> **NOTE:** Don't abuse `useBrowserVisibleTask$()` when the same logic can be achieved using `useTask$()` or other means. Ask to yourself: Does this code really need to run at the beginning in the browser? If the answer is no, `useBrowserVisibleTask$()` is probably not the right answer.
> **NOTE:** Don't abuse `useVisibleTask$()` when the same logic can be achieved using `useTask$()` or other means. Ask to yourself: Does this code really need to run at the beginning in the browser? If the answer is no, `useVisibleTask$()` is probably not the right answer.
As the name implies, `useBrowserVisibleTask$()` is useful when you need to run some code when the component becomes visible in the viewport. This is useful for:
As the name implies, `useVisibleTask$()` is useful when you need to run some code when the component becomes visible in the viewport. This is useful for:

- Run code BEFORE user interaction, like animations, or other logic that needs to run before user interaction.
- Read the DOM after rendering
Expand Down
6 changes: 3 additions & 3 deletions packages/docs/src/routes/docs/components/overview/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -110,13 +110,13 @@ For a detailed discussion of reactivity, see related discussion.
Qwik provides the ability to store a reference to any component. To do so, you have to create a signal and pass the signal as `ref` attribute to the component. After the component was mounted, the reference has been stored on the signal. Have a look at the example below:

```tsx
import { component$, useBrowserVisibleTask$, useSignal } from '@builder.io/qwik';
import { component$, useVisibleTask$, useSignal } from '@builder.io/qwik';

export default component$(() => {
const width = useSignal(0);
const height = useSignal(0);
const outputRef = useSignal<Element>();
useBrowserVisibleTask$(() => {
useVisibleTask$(() => {
if (outputRef.value) {
const rect = outputRef.value.getBoundingClientRect();
width.value = Math.round(rect.width);
Expand Down Expand Up @@ -226,7 +226,7 @@ The Optimizer splits Qwik components into the host element and the behavior of t

- [`useTask$()`](../lifecycle/index.mdx#usetask) - defines a callback that will be called before render and/or when a watched store changes
- [`useResource$()`](../resource/index.mdx) - creates a resource to asyncronously load data
- [`useBrowserVisibleTask$()`](../lifecycle/index.mdx#usebrowservisibletask) - defines a callback that will be called after render in the client only (browser)
- [`useVisibleTask$()`](../lifecycle/index.mdx#usebrowservisibletask) - defines a callback that will be called after render in the client only (browser)

### Other

Expand Down
4 changes: 2 additions & 2 deletions packages/docs/src/routes/docs/components/state/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -290,14 +290,14 @@ Thanks to the fine grained reactivity of Qwik, only the components that depend o
Sometimes, you may want to store a value in the state, but you don't want it to be serialized. This is useful for storing values that are not serializable, like functions, or classes.

```tsx
import { component$, useStore, noSerialize, useBrowserVisibleTask$ } from '@builder.io/qwik';
import { component$, useStore, noSerialize, useVisibleTask$ } from '@builder.io/qwik';

export const App = component$(() => {
const state = useStore({
monacoInstance: null,
});

useBrowserVisibleTask$(() => {
useVisibleTask$(() => {
// Monaco is not serializable, so we can't store it in the state using `noSerialize()`
state.monacoInstance = noSerialize(new Monaco());
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,4 @@ While not a common use case, you may occasionally need to process events synchro

Since Qwik processes asynchronously by default, your code must be explicitly configured for synchronous calls. This example shows how to eagerly load an event handler that processes a synchronous event.

> **Your task:** Convert the `onClick$` from asynchronous event to synchronous event by using [`useBrowserVisibleTask$`](https://qwik.builder.io/docs/components/lifecycle/#usebrowservisibletask) lifecycle and [normal event registration](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener).
> **Your task:** Convert the `onClick$` from asynchronous event to synchronous event by using [`useVisibleTask$`](https://qwik.builder.io/docs/components/lifecycle/#usebrowservisibletask) lifecycle and [normal event registration](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener).
10 changes: 8 additions & 2 deletions packages/qwik/src/core/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -914,10 +914,10 @@ export interface Tracker {
// @alpha (undocumented)
export const untrack: <T>(fn: () => T) => T;

// @public
// @alpha @deprecated (undocumented)
export const useBrowserVisibleTask$: (first: TaskFn, opts?: OnVisibleTaskOptions | undefined) => void;

// @public
// @alpha @deprecated (undocumented)
export const useBrowserVisibleTaskQrl: (qrl: QRL<TaskFn>, opts?: OnVisibleTaskOptions) => void;

// @alpha @deprecated
Expand Down Expand Up @@ -1060,6 +1060,12 @@ export const useTaskQrl: (qrl: QRL<TaskFn>, opts?: UseTaskOptions) => void;
// @alpha @deprecated (undocumented)
export const useUserContext: typeof useServerData;

// @public
export const useVisibleTask$: (first: TaskFn, opts?: OnVisibleTaskOptions | undefined) => void;

// @public
export const useVisibleTaskQrl: (qrl: QRL<TaskFn>, opts?: OnVisibleTaskOptions) => void;

// @beta @deprecated (undocumented)
export const useWatch$: (first: TaskFn, opts?: UseTaskOptions | undefined) => void;

Expand Down
8 changes: 4 additions & 4 deletions packages/qwik/src/core/examples.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { $, QRL } from './qrl/qrl.public';
import { useOn, useOnDocument, useOnWindow } from './use/use-on';
import { useStore } from './use/use-store.public';
import { useStyles$, useStylesScoped$ } from './use/use-styles';
import { useBrowserVisibleTask$, useTask$ } from './use/use-task';
import { useVisibleTask$, useTask$ } from './use/use-task';
import { implicit$FirstArg } from './util/implicit_dollar';

//////////////////////////////////////////////////////////
Expand Down Expand Up @@ -309,7 +309,7 @@ export const CmpInline = component$(() => {
count: 0,
});

useBrowserVisibleTask$(() => {
useVisibleTask$(() => {
// Only runs in the client
const timer = setInterval(() => {
store.count++;
Expand Down Expand Up @@ -360,7 +360,7 @@ export const CmpInline = component$(() => {
const counterStore = useStore({
value: 0,
});
useBrowserVisibleTask$(() => {
useVisibleTask$(() => {
// Only runs in the client
const timer = setInterval(() => {
counterStore.value += step;
Expand Down Expand Up @@ -388,7 +388,7 @@ export const CmpInline = component$(() => {
const Cmp = component$(() => {
const input = useRef<HTMLInputElement>();

useBrowserVisibleTask$(({ track }) => {
useVisibleTask$(({ track }) => {
const el = track(() => input.current)!;
el.focus();
});
Expand Down
1 change: 1 addition & 0 deletions packages/qwik/src/core/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ export { useWatch$, useWatchQrl } from './use/use-task';
export type { ResourceProps, ResourceOptions } from './use/use-resource';
export { useResource$, useResourceQrl, Resource } from './use/use-resource';
export { useTask$, useTaskQrl } from './use/use-task';
export { useVisibleTask$, useVisibleTaskQrl } from './use/use-task';
export { useComputed$, useComputedQrl } from './use/use-task';
export { useBrowserVisibleTask$, useBrowserVisibleTaskQrl } from './use/use-task';
export { useClientEffect$, useClientEffectQrl } from './use/use-task';
Expand Down
6 changes: 3 additions & 3 deletions packages/qwik/src/core/render/dom/render.unit.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { component$ } from '../../component/component.public';
import { inlinedQrl } from '../../qrl/qrl';
import { useLexicalScope } from '../../use/use-lexical-scope.public';
import { useStore } from '../../use/use-store.public';
import { useBrowserVisibleTask$, useTask$ } from '../../use/use-task';
import { useVisibleTask$, useTask$ } from '../../use/use-task';
import { useCleanup$, useOn } from '../../use/use-on';
import { Slot } from '../jsx/slot.public';
import { render } from './render.public';
Expand Down Expand Up @@ -971,7 +971,7 @@ export const Transparent = component$(() => {
});

export const UseEvents = component$(() => {
useBrowserVisibleTask$(() => {
useVisibleTask$(() => {
console.warn('hello');
});
useOn(
Expand Down Expand Up @@ -1012,7 +1012,7 @@ export const Hooks = component$(() => {
};
});

useBrowserVisibleTask$(() => {
useVisibleTask$(() => {
effectDiv.current!.textContent = 'true';
return () => {
effectDestroyDiv.current!.textContent = 'true';
Expand Down
16 changes: 8 additions & 8 deletions packages/qwik/src/core/render/ssr/render-ssr.unit.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { useOn, useOnDocument, useOnWindow } from '../../use/use-on';
import { Ref, useRef } from '../../use/use-ref';
import { Resource, useResource$ } from '../../use/use-resource';
import { useStylesScopedQrl, useStylesQrl } from '../../use/use-styles';
import { useBrowserVisibleTask$, useTask$ } from '../../use/use-task';
import { useVisibleTask$, useTask$ } from '../../use/use-task';
import { delay } from '../../util/promises';
import { SSRComment } from '../jsx/utils.public';
import { Slot } from '../jsx/slot.public';
Expand Down Expand Up @@ -1569,10 +1569,10 @@ export const ContextConsumer = component$(() => {
});

export const UseClientEffect = component$((props: any) => {
useBrowserVisibleTask$(() => {
useVisibleTask$(() => {
console.warn('client effect');
});
useBrowserVisibleTask$(() => {
useVisibleTask$(() => {
console.warn('second client effect');
});
useTask$(async () => {
Expand All @@ -1584,10 +1584,10 @@ export const UseClientEffect = component$((props: any) => {
});

export const UseEmptyClientEffect = component$(() => {
useBrowserVisibleTask$(() => {
useVisibleTask$(() => {
console.warn('client effect');
});
useBrowserVisibleTask$(() => {
useVisibleTask$(() => {
console.warn('second client effect');
});
useTask$(async () => {
Expand All @@ -1598,7 +1598,7 @@ export const UseEmptyClientEffect = component$(() => {
});

export const HeadCmp = component$(() => {
useBrowserVisibleTask$(() => {
useVisibleTask$(() => {
console.warn('client effect');
});
return (
Expand Down Expand Up @@ -1678,14 +1678,14 @@ export const NullCmp = component$(() => {
});

export const EffectTransparent = component$(() => {
useBrowserVisibleTask$(() => {
useVisibleTask$(() => {
console.warn('log');
});
return <Slot />;
});

export const EffectTransparentRoot = component$(() => {
useBrowserVisibleTask$(() => {
useVisibleTask$(() => {
console.warn('log');
});
return (
Expand Down
2 changes: 1 addition & 1 deletion packages/qwik/src/core/state/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ class ReadWriteProxyHandler implements ProxyHandler<TargetType> {
const invokeCtx = tryGetInvokeContext();
if (invokeCtx && invokeCtx.$event$ === RenderEvent) {
logError(
'State mutation inside render function. Move mutation to useTask$() or useBrowserVisibleTask$()',
'State mutation inside render function. Move mutation to useTask$() or useVisibleTask$()',
prop
);
}
Expand Down
4 changes: 2 additions & 2 deletions packages/qwik/src/core/use/use-on.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { Task, WatchFlagsIsCleanup } from './use-task';
*
* @alpha
* @deprecated Use the cleanup() function of `useTask$()`, `useResource$()` or
* `useBrowserVisibleTask$()` instead.
* `useVisibleTask$()` instead.
*/
// </docs>
export const useCleanupQrl = (unmountFn: QRL<() => void>): void => {
Expand All @@ -39,7 +39,7 @@ export const useCleanupQrl = (unmountFn: QRL<() => void>): void => {
*
* @alpha
* @deprecated Use the cleanup() function of `useTask$()`, `useResource$()` or
* `useBrowserVisibleTask$()` instead.
* `useVisibleTask$()` instead.
*/
// </docs>
export const useCleanup$ = /*#__PURE__*/ implicit$FirstArg(useCleanupQrl);
Expand Down
2 changes: 1 addition & 1 deletion packages/qwik/src/core/use/use-ref.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export interface Ref<T = Element> {
* const Cmp = component$(() => {
* const input = useRef<HTMLInputElement>();
*
* useBrowserVisibleTask$(({ track }) => {
* useVisibleTask$(({ track }) => {
* const el = track(() => input.current)!;
* el.focus();
* });
Expand Down
2 changes: 1 addition & 1 deletion packages/qwik/src/core/use/use-store.public.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ export interface UseStoreOptions {
* const counterStore = useStore({
* value: 0,
* });
* useBrowserVisibleTask$(() => {
* useVisibleTask$(() => {
* // Only runs in the client
* const timer = setInterval(() => {
* counterStore.value += step;
Expand Down
Loading

0 comments on commit fc078e5

Please sign in to comment.