Try   HackMD

Passing signals through dumb components

import { component$, useStore, QRL } from "@builder.io/qwik"; export const App = component$(() => { const store1 = useStore({ count: 0 }); const store2 = useStore({ count: 0 }); return ( <button onClick$={() => store1.count++}> // PROBLEM: Root should always re-render // because we don't know that `store` is constant <CountStore store={Math.random() > 0.5 ? store1 : store2} /> <CountStore store{store1} /> <PassThrough value$={() => store1.count + 1} /> </button> ); }); export const PassThrough = component$( (props: { valueQrl?: QRL<() => number> }) => { return <CountRef valueQrl={props.valueQrl} />; } ); export const CountStore = component$((props: { store: { count: number } }) => { useTrack(props, 'store'); return <span>{props.store.count}</span>; }); export const CountRef = component$( (props: { store?: { count: number }; valueQrl?: QRL<() => number> }) => { return <span>{props.valueQrl?.invoke()}</span>; } );

Options:

  • mutable: you must always re-render the template because there is just no way of knowing if re-rendering will produce the same values.
  • marking mutable: If marked than same as above.
  • passing signals:
    • SolidJS can cheat because it can create getters (which are not serializable) We can explore what would it mean to make getters serializable.
  • immutable: all component props are always immutable! Must pass stores or QRL for computed values.

Solutions Space

  • The callee of the component (not the component itself) knows if a binding is constant or not and should be the one determining it through syntax.
    • All bindings are const by default
    • A binding can become var through marker
<ChildComponent title={mutable(expr)}/>