Frequently Asked Questions
General
Does Anchor replace SolidJS?
No. Anchor enhances SolidJS's already excellent reactivity system by adding direct mutation support, schema validation, and powerful state management patterns while preserving SolidJS's fine-grained reactivity.
Why do I need Anchor if SolidJS already has signals?
SolidJS signals are excellent for primitives, but Anchor adds direct mutation for objects/arrays, schema validation with Zod, two-way data binding, and async state management with built-in status tracking.
Doesn't mutating state directly break reactivity?
Not with Anchor. It uses Proxies to intercept mutations and trigger fine-grained reactivity automatically. Anchor implements its own reactivity system that integrates with SolidJS components.
Performance
Does Anchor add overhead to SolidJS?
Minimal. Anchor implements its own fine-grained reactivity system via @anchorlib/core, then integrates with SolidJS components. The proxy layer adds negligible overhead while providing significant developer experience improvements.
How does Fine-Grained Reactivity work?
Anchor implements its own fine-grained reactivity system. When you mutate state.count++, only components reading state.count update—nothing else re-runs. This gives you the same fine-grained performance as SolidJS signals.
When should I use Anchor vs plain signals?
- Plain signals: When you need SolidJS's native reactivity and don't need two-way binding (you'll pass getter/setter separately)
- Anchor
mutable(): When you need direct mutation, two-way binding with$bind(), or complex nested state - Anchor
form(): Forms with validation - Anchor
query(): Async operations with status tracking
Note: Signals require passing value={signal()} and onChange={setSignal} separately. Anchor's $bind() provides true two-way binding.
Business & Impact
Is it hard to learn?
No. If you know JavaScript objects and SolidJS basics, you already know Anchor. Direct mutations (state.count++) are more intuitive than signal setters (setCount(c => c + 1)).
Does Anchor reduce development costs?
Yes. By eliminating boilerplate for forms, async state, and two-way binding, teams ship features faster. Schema validation catches bugs at runtime before they reach production.
How does it affect AI coding?
Anchor is AI-friendly. Its declarative patterns (direct mutations, automatic tracking) require fewer tokens than imperative signal management, making it ideal for AI-assisted development.
Is maintenance cheaper?
Yes. Direct mutations are easier to understand than complex signal dependencies. Schema validation ensures data integrity, reducing runtime bugs in production.
Comparison
How is this different from SolidJS stores?
SolidJS stores use createStore() with immutable updates via produce(). Anchor uses direct mutations on proxies, which is simpler and more intuitive. Both provide fine-grained reactivity, but with different APIs.
Is this like MobX?
Similar concept (observable proxies with automatic tracking). Both use proxies to intercept mutations and trigger reactivity. Anchor's @anchorlib/core implements its own tracking mechanism, then @anchorlib/solid integrates it with SolidJS's reactivity system.
Can I use Anchor with SolidJS signals?
Yes! Anchor state (mutable(), immutable()) and SolidJS signals work side-by-side. Use createEffect() for signals and effect() for Anchor state. They're complementary, not exclusive.
Component Architecture
Do I need special component wrappers?
No. Anchor works with standard SolidJS function components. Only use bindable() HOC when you need two-way data binding props.
Can I use SolidJS control flow?
Absolutely! Use <Show>, <For>, <Switch>, and <Match> as normal. Anchor state works seamlessly with all SolidJS control flow components.
Can I use SolidJS lifecycle hooks?
Yes. onMount, onCleanup, and other SolidJS lifecycle hooks work perfectly with Anchor state. Use them as you normally would.
State Management
Is mutable state safe?
Yes. Anchor uses immutable() + writable() for shared state, enforcing read-only public interfaces with controlled write access. This ensures unidirectional data flow.
Does it track nested properties?
Yes. mutable() tracks nested objects and arrays by default. Mutating state.user.name only updates components reading that specific property.
Can I validate my state?
Yes. Anchor supports Zod schemas for both mutable() and form(). Invalid data is rejected at runtime, ensuring type safety beyond TypeScript.
Reactivity System
How do effects work?
Anchor's effect() automatically tracks dependencies. Unlike SolidJS's createEffect(), it only tracks Anchor state. For SolidJS signals, use createEffect() instead.
Do I need dependency arrays?
No. Effects track dependencies automatically based on what you read during execution. No manual arrays, no stale closures.
How do I stop tracking?
Use untrack() to read data without subscribing to it. This is useful for reading configuration or performing side effects without creating dependencies.
What if I need a copy of the state?
Use snapshot() to create a non-reactive deep clone. This is useful for logging, serialization, or passing data to external APIs.
Forms & Validation
How do I handle forms?
Use form() with a Zod schema. It returns [state, errors] where state is mutable and errors updates automatically as you type.
Can I validate on submit only?
Yes. Use schema.safeParse(state) in your submit handler. The form() helper validates on change by default, but you control when to check errors.
How do I show validation errors?
Use <Show when={errors.fieldName}> to conditionally render error messages. Errors update automatically as the user types.
Async Operations
How do I handle async data?
Use query() for general async operations, fetchState() for HTTP requests, or streamState() for streaming responses. All include automatic status tracking.
Do I need to manage loading states manually?
No. query(), fetchState(), and streamState() all provide a status property ('idle' | 'pending' | 'success' | 'error') that updates automatically.
How do I cancel requests?
Async functions receive an AbortSignal parameter. Pass it to fetch() and Anchor handles cancellation automatically when a new request starts or the component unmounts.
Two-Way Binding
How do I do two-way binding?
Use bindable() HOC to create components that accept Bindable<T> props, then use $bind(state, 'key') to pass a writable reference to the child component.
When should I use two-way binding?
For reusable form inputs, custom controls, or any component that needs to modify parent state directly. For simple cases, just pass value and onChange callbacks.
Can I bind to primitives?
Yes. Use $bind(mutableRef) for primitives (no key needed) or $bind(object, 'key') for object properties.
Ecosystem
Does it work with SolidStart?
Yes. Anchor state works in both client and server components. Just be careful with module-level state in SSR—use SolidJS Context for request-scoped state.
Can I use it with existing SolidJS libraries?
Absolutely. Anchor is just state management—it works alongside any SolidJS library. Use it with SolidJS Router, SolidJS Meta, or any other ecosystem tool.
Does it work with TypeScript?
Yes. Anchor is written in TypeScript with full type inference. Schemas provide runtime validation that complements TypeScript's compile-time checking.