# A more general way to decompose functions in Qwik ## Problem Description Qwik gains its power by breaking a component into individual functions which can be lazy loaded. In order to do that Qwik places restrictions over what symbols a function is allowed to close over. This proposal relaxes the constrains so that a more free form code is accepted by Qwik. This work also lays path for `useEffect`-like API. ## Example Developer writes (TypeScript): ```typescript= import {qComponent, useState, onRender} from '@builder.io/qwik'; export const Buttons = [ { label: '+', value: 1 }, { label: '-', value: -1 }, ] const Counter = qComponent((props: {value?: number}) => { const state = useState({count: props.value || 0}); onRender(() => ( <> <span>{state.count}</span> {Buttons.map((btn) => ( <button on:click={() => state.count += btn.value}> {btn.label} </button> ))} </> )); }); ``` Optimizer output (JavaScript): ```javascript= import {qComponent, useState} from '@builder.io/qwik'; // imports for the compiler import {captureRef, useClosure} from '@builder.io/qwik'; export const Counter_onMount = (props) => { const closure = useClosure(); closure.state = useState({count: props.value || 0}); }; export const Counter_onRender = () => { const {state} = useClosure(); return ( <> <span>{state.count}</span> <button on:click={qHook('./foo.js#Counter_onClick', [state])}>+</button> </> ); } export const Counter_onClick = () => { const {state} = useClosure(); return state.count++; } const Counter = qComponent({ onMount: qHook('./foo.js#Counter_onMount', 'Counter_onMount', [captureRef(0)]), onRender: qHook('./foo.js#Counter_onRender', 'Counter_onRender', [captureRef(0)]), }) ``` - `Q:` Why use `useClosure()` instead of assuming that it passed as argument? - `A:` Because we want to keep `qwikloader` simple and we don't want to have to teach it how to look for these arguments. - `Q:` Without optimizer there is no way to control the variables captured by the closures. - `A:` In dev mode we will rely on the fact that we can run the `qComponent` creation multiple times, each generating a unique QRL. This will result in memory leak, but it should be good enough to run all of the tests. # What changed - `qHook` is only required to be generated by the Optimizer, not by developer. - New set of marker functions for the Optimizer: - `qComponent`: Turn into `qComponent({onMount: qHook(...)})` - `onRender` (and friends): `qComponent({onRender: qHook(...)})` - Any `on:`/`onWindow:`/`onDocument:` property in JSX: `qHook(...)`