diff --git a/packages/docs/src/routes/demo/events/custom-event/index.tsx b/packages/docs/src/routes/demo/events/custom-event/index.tsx new file mode 100644 index 00000000000..2d9b6bf6fe0 --- /dev/null +++ b/packages/docs/src/routes/demo/events/custom-event/index.tsx @@ -0,0 +1,41 @@ +import { component$, Slot, useStore } from '@builder.io/qwik'; + +export default component$(() => { + return ( + + ); +}); + +type ButtonProps = { + onTripleClick$: () => void; +}; + +export const Button = component$(({ onTripleClick$ }) => { + const state = useStore({ + clicks: 0, + lastClickTime: 0, + }); + return ( + + ); +}); diff --git a/packages/docs/src/routes/demo/events/prop-function/index.tsx b/packages/docs/src/routes/demo/events/prop-function/index.tsx deleted file mode 100644 index 0084025142b..00000000000 --- a/packages/docs/src/routes/demo/events/prop-function/index.tsx +++ /dev/null @@ -1,16 +0,0 @@ -import { type PropFunction, component$, Slot } from '@builder.io/qwik'; - -export default component$(() => { - return alert('CLICKED!')}>click me!; -}); - -export const CmpButton = component$<{ - // Important to tell TypeScript that this is async - onClick$?: PropFunction<() => void>; -}>((props) => { - return ( - - ); -}); diff --git a/packages/docs/src/routes/docs/(qwik)/components/events/index.mdx b/packages/docs/src/routes/docs/(qwik)/components/events/index.mdx index e12b7e5d1db..a4921e00fbc 100644 --- a/packages/docs/src/routes/docs/(qwik)/components/events/index.mdx +++ b/packages/docs/src/routes/docs/(qwik)/components/events/index.mdx @@ -15,6 +15,7 @@ contributors: - AnthonyPAlicea - amatiash - harishkrishnan24 + - maiieul --- import CodeSandbox from '../../../../../components/code-sandbox/index.tsx'; @@ -234,37 +235,65 @@ export default component$(() => { > **NOTE** Using `VisibleTask` to listen for events is an anti-pattern in Qwik because it causes eager execution of code in the browser defeating [resumability](/docs/(qwik)/concepts/resumable/index.mdx). Only use it when you have no other choice. Most of the time, you should use JSX to listen for events: `
` or `useOn(...)` event methods if you need to listen programmatically. -## `PropFunction` +## Custom event props -When creating your components it is often useful to pass what looks like event handlers, (even though they are not DOM events, only callbacks.) Component boundaries in Qwik must be serializable, and functions are not serializable unless they are converted to a QRL using an optimizer. This is done through `$` suffix. QRLs are asynchronous and therefore we need to tell TypeScript that the function can't be called synchronously, we do this through `PropFunction` type. +When creating your components it is often useful to pass custom event props that look like event handlers, (even though they are not DOM events, only callbacks). Component boundaries in Qwik must be serializable for the optimizer to split them up into separate chunks, and functions are not serializable unless they are converted to a QRL using the `$` sign. +When typing `component$` with the Generics syntax, Qwik will handle the type transformation automatically for you. + ```tsx - alert('CLICKED!')}>click me! -``` - -The above is not possible because `onClick` is a function that is not serializable. Instead, we need to tell Optimizer to convert our function into a QRL. This is done by naming the property with `$` suffix as in this example. - - -```tsx -import { type PropFunction, component$, Slot } from '@builder.io/qwik'; +import { component$, Slot, useStore } from '@builder.io/qwik'; export default component$(() => { - return alert('CLICKED!')}>click me!; + return ( + + ); }); -export const CmpButton = component$<{ - // Important to tell TypeScript that this is async - onClick$?: PropFunction<() => void>; -}>((props) => { +type ButtonProps = { + onTripleClick$: () => void; +}; + +export const Button = component$(({ onTripleClick$ }) => { + const state = useStore({ + clicks: 0, + lastClickTime: 0, + }); return ( - ); }); + ``` +⚠️ When using type annotations, we need to wrap the event type with `PropFunction` in order to tell TypeScript that the function can't be called synchronously. +```tsx +component$(({ onTripleClick$ } : { onTripleClick$?: PropFunction<() => void> }) => { + ... +}); +``` + ## Window and Document events So far, we have discussed how to listen to events that originate from elements. There are events (for example, `scroll` and `mousemove`) that require that we listen to them on the `window` or `document`. For this reason, Qwik allows for the `document:on` and `window:on` prefixes when listening for events.