Solid guide
The Solid adapter drives the same native Fabric engine as React, Vue, Svelte,
and Angular, through solid-js/universal’s own official custom-renderer API,
the framework-agnostic seam Solid ships for non-DOM targets. Compiled Solid
JSX becomes calls into the engine’s mutation API directly; Fabric commits the
real native views.
The one thing to internalize before writing a component: a Solid component body runs once, not on every update, unlike React, Vue, Svelte, and Angular. Reactivity crosses through signals and accessors instead of re-invoking the function. See the Solid reactivity guide for what that changes about props, refs, and render children.
The examples/solid canary - the same component surface and engine as the
React, Vue, Svelte, and Angular canaries, driven through
solid-js/universal instead.
Minimal component
Section titled “Minimal component”import { createSignal } from 'solid-js';import './App.css';
export default function App() { const [count, setCount] = createSignal(0);
return ( <view class="root"> <pressable onPress={() => setCount(count() + 1)}> <text class="label">Count is {count()}</text> </pressable> </view> );}.root { flex: 1; align-items: center; justify-content: center;}.label { font-size: 24px;}view, pressable, and text are intrinsic tags — no import needed. Only a
composed component (FlatList, SectionList, VirtualizedList,
VirtualizedSectionList, KeyboardAvoidingView, …) still comes from
@symbiote-native/solid.
StyleSheet.create works identically if you’d rather keep style objects
inline instead of a CSS file - see the Styling guide
for both paths.
Solid contract
Section titled “Solid contract”- events are real camelCase props (
onPress={onTap},onLongPress,onValueChange,onLayout): compiled JSX passes them straight through, no directive and no kebab-case normalization step; - children are ordinary Solid JSX. A component that hands state back to its
children (
Pressable’spressed) takes a function child called with an accessor, not a snapshot:<pressable>{state => <text>{state().pressed ? 'Release' : 'Press me'}</text>}</pressable>. Passing a snapshot value here is how the other adapters spell the same thing, and it is the one place copying their shape verbatim breaks Solid - see the reactivity guide; - refs are plain
ref={callback}: Solid rewritesref={el}into a callback prop at compile time, and every SymbioteNative component grafts the imperative host API (measure,setNativeProps,focus, …) onto the node a ref receives, exactly like React’sgetPublicInstance; - styles:
style/classprops, plusStyleSheet.createif you’d rather avoid CSS entirely; - the two reactive lifecycle primitives are spelled
createColorScheme()/createWindowDimensions(), notuseColorScheme/useWindowDimensions: Solid’s own convention reservesuse*for consuming something that already exists (useContext,useTransition), while a function that owns a subscription iscreate*.useNavigation/useRoutefrom@symbiote-native/navigationkeep theuse*form for the same reason: they consume an existing router, they don’t create one; - both cross-tree content primitives are here:
Portal(<Portal mount={target}>, same-surface, the twin of React’screatePortal) andcreateTunnel(cross-surface, matching every other adapter).
Read the exact API surface in the Solid API reference.