UNPKG

seitu

Version:
173 lines (118 loc) • 4.46 kB
# Solid (seitu/solid) ## useSubscription Core Solid primitive from `seitu/solid`. Returns a Solid `Accessor<T>` (`() => T`) that stays in sync with the source. Works with any `Subscribable<T> & Readable<T>`. Accepts a raw instance or a reactive getter. ### Basic usage (module-level instance) ```tsx import { useSubscription } from 'seitu/solid' import { createStore } from 'seitu' const count = createStore(0) function Counter() { const value = useSubscription(count) return <button onClick={() => count.set(v => v + 1)}>{value()}</button> } ``` ### Inline subscription (getter form) ```tsx import { useSubscription } from 'seitu/solid' import { createScrollState } from 'seitu/web' function ScrollTracker() { let ref: HTMLDivElement | undefined const state = useSubscription(() => createScrollState({ element: () => ref, direction: 'vertical' }) ) return <div ref={ref}>{state().top.reached ? 'at top' : 'scrolled'}</div> } ``` ### Reactive source (re-subscribes when a signal changes) ```tsx import { createSignal } from 'solid-js' import { useSubscription } from 'seitu/solid' import { createWebStorageValue } from 'seitu/web' function UserStorage(props: { userId: string }) { const data = useSubscription(() => createWebStorageValue({ type: 'localStorage', key: `user:${props.userId}`, schema, defaultValue }) ) return <div>{data().name}</div> } ``` ### With selector (granular updates) ```tsx const count = useSubscription(storage, { selector: v => v.count }) // count() only changes when the selected value changes ``` ### Options | Option | Type | Description | |--------|------|-------------| | `selector?` | `(value) => R` | Derive subset; the accessor updates only when it changes | | `isEqual?` | `(prev, next) => boolean` | Custom equality (default: `deepEqual`) | ### Returns `Accessor<R>` — a getter function. Read it with `value()` inside JSX or any tracked scope. ## Subscription (render-prop component) Declarative render-prop component from `seitu/solid`. The children function runs once and receives a Solid `Accessor<R>` — read it with `value()` so updates stay fine-grained. ```tsx import { Subscription } from 'seitu/solid' <Subscription value={storage}> {value => <div>{value().count}</div>} </Subscription> <Subscription value={storage} selector={v => v.count}> {count => <div>{count()}</div>} </Subscription> ``` ### Props | Prop | Type | Description | |------|------|-------------| | `value` | `Subscribable & Readable` | The reactive source | | `selector?` | `(value) => R` | Optional selector for granular updates | | `children` | `(value: Accessor<R>) => JSX.Element` | Render function receiving an accessor | ## Common Mistakes ### [CRITICAL] Reading the accessor without calling it Wrong: ```tsx const value = useSubscription(store) return <div>{value}</div> ``` Correct: ```tsx const value = useSubscription(store) return <div>{value()}</div> ``` `useSubscription` returns a Solid `Accessor`; you must call it (`value()`) to read and track the value. The same applies to the `Subscription` component's children argument — call it (`value()`) inside JSX, don't treat it as a plain value. ### [HIGH] Passing reactive props directly instead of a getter Wrong: ```tsx function Item(props: { store: Store<number> }) { const value = useSubscription(props.store) } ``` Correct: ```tsx function Item(props: { store: Store<number> }) { const value = useSubscription(() => props.store) } ``` Reading `props.store` outside a tracked scope loses reactivity; the getter form re-subscribes when the prop changes. ### [CRITICAL] Importing from seitu/react in Solid Wrong: ```ts import { useSubscription } from 'seitu/react' ``` Correct: ```ts import { useSubscription } from 'seitu/solid' ``` Solid apps must use the `seitu/solid` primitive/component — the React versions rely on `useSyncExternalStore` and React internals. ### [LOW] Preferring the component over the primitive without reason Wrong: ```tsx <Subscription value={s}>{v => <Child value={v()} />}</Subscription> ``` Correct: ```tsx const v = useSubscription(s); return <Child value={v()} /> ``` `useSubscription` is simpler for most cases; `Subscription` is for render-prop composition. ## See also - [`create-scroll-state`](create-scroll-state.md) — Scroll tracking uses the getter + ref pattern in Solid. ## Source `src/solid/hooks/index.ts`, `src/solid/components/index.ts`