Counter example
This example shows state, native layout, text, and a press event.
import './App.css';import { useState } from 'react';
export default function App() { const [count, setCount] = useState(0);
return ( <view className="root" onPress={() => setCount(value => value + 1)}> <text className="text">Count is {count}</text> </view> );}.root { flex: 1; align-items: center; justify-content: center; }.text { font-size: 24px; }<script setup lang="ts">import { ref } from 'vue';
const count = ref(0);</script>
<template> <view class="root" @press="count += 1"> <text class="text">Count is {{ count }}</text> </view></template>
<style scoped>.root { flex: 1; align-items: center; justify-content: center; }.text { font-size: 24px; }</style>import { Component } from '@angular/core';import { SYMBIOTE_ELEMENTS } from '@symbiote-native/angular';import './app.css';
@Component({ selector: 'app-root', standalone: true, imports: [SYMBIOTE_ELEMENTS], template: ` <view class="root"> <pressable (press)="count = count + 1"> <text class="text">Count is {{ count }}</text> </pressable> </view> `,})export class App { count = 0;}.root { flex: 1; align-items: center; justify-content: center; }.text { font-size: 24px; }<script lang="ts"> let count = $state(0);</script>
<!-- A press callback on a bare host tag goes through the `p={{ … }}` bag — an individual `onPress={…}` attribute is silently misrouted through Svelte's own DOM event system instead of the engine. --><view class="root" p={{ onPress: () => (count += 1) }}> <text class="text">Count is {count}</text></view>
<style> .root { flex: 1; align-items: center; justify-content: center; } .text { font-size: 24px; }</style>import './App.css';import { createSignal } from 'solid-js';
export function App() { const [count, setCount] = createSignal(0);
return ( <view class="root" onPress={() => setCount(value => value + 1)}> <text class="text">Count is {count()}</text> </view> );}.root { flex: 1; align-items: center; justify-content: center; }.text { font-size: 24px; }What changed
Section titled “What changed”| Concern | React | Vue | Angular | Svelte | Solid |
|---|---|---|---|---|---|
| State | useState() |
ref() |
plain class field | $state() rune |
createSignal() |
| Press event | onPress directly on view |
@press directly on view |
(press) on a pressable tag |
onPress via a p={{ onPress }} bag |
onPress directly on view |
| Styling | className="root" + App.css |
class="root" + SFC <style> |
class="root" + app.css |
class="root" + component <style> |
class="root" + App.css |
| Native path | shared engine | shared engine | shared engine | shared engine | shared engine |
The view tag itself carries onPress/onPressIn/onPressOut — React, Vue,
and Solid’s simplest counter reaches for it directly rather than wrapping in
pressable. Svelte needs the same handlers wrapped in a p={{ … }} bag
because an individual on* attribute on a bare host tag is intercepted by
Svelte’s own compiled event system rather than reaching the engine directly.
Angular’s counter uses the pressable tag here since its non-function-children
form is the idiomatic starting point on that adapter; either works on every
adapter (see the Pressable example).
StyleSheet.create works identically to a CSS class if you’d rather keep
style objects inline — see the Styling guide.