# How to: handle press/change events

> Wiring the same native event across React, Vue, Angular, Svelte, and Solid.

You need to react to a native event (a tap, a value change), and the public
shape of that event differs by framework.

<Tabs syncKey="framework">
  <TabItem label="React">
    Callback props — the classic imperative style.

    ```tsx
    <pressable onPress={() => setCount(count + 1)} />
    <switch value={enabled} onValueChange={setEnabled} />
    <text-input value={name} onValueChange={setName} />
    ```

  </TabItem>
  <TabItem label="Vue">
    Typed emits, or `v-model` sugar on controlled components.

    ```vue
    <pressable @press="count++" />
    <switch v-model="enabled" />
    <text-input v-model="name" />
    ```

  </TabItem>
  <TabItem label="Angular">
    Real `@Output()` `EventEmitter`s carry the event across the boundary. The component's
    `imports: [SYMBIOTE_ELEMENTS]` is what makes the lowercase tags compile.

    ```ts
    template: `
      <pressable (press)="count = count + 1" />
      <switch [value]="enabled" (valueChange)="setEnabled($event)" />
      <text-input [value]="name" (valueChange)="setName($event)" />
    `
    ```

  </TabItem>
  <TabItem label="Svelte">
    Callback props too — Svelte has no directive-based binding sugar for a
    native control (see [two-way binding](/docs/howtos/two-way-binding/)), so
    this looks just like React's.

    ```svelte
    <pressable onPress={() => (count += 1)} />
    <switch value={enabled} onValueChange={(next) => (enabled = next)} />
    <text-input value={name} onValueChange={(next) => (name = next)} />
    ```

  </TabItem>
  <TabItem label="Solid">
    Callback props too, over signals — no directive sugar, same flat-bag
    naming as React and Svelte.

    ```tsx
    <pressable onPress={() => setCount(count() + 1)} />
    <switch value={enabled()} onValueChange={setEnabled} />
    <text-input value={name()} onValueChange={setName} />
    ```

  </TabItem>
</Tabs>

<Aside type="caution" title="Scroll events are the one exception">
  `onScroll`/`onScrollBeginDrag`/`onScrollEndDrag`/`onMomentumScrollBegin`/
  `onMomentumScrollEnd` stay plain callback `@Input()`s on Angular, even on
  `ScrollView` and the lists — RN's scroll callbacks can carry an
  `Animated.event(...)` marker, and `@Output()` can only bind a template
  listener expression, not an arbitrary value.
</Aside>

## Same payload, different naming

`TextInput`'s React/Vue/Svelte callback merges what used to be two native
callbacks into one `onValueChange(text, event)` — an `EventEmitter` can't
carry two values, so Angular keeps `(valueChange)` text-only and adds a
separate `(change)` output for the raw event.

For the full event-naming table and why a given event became a Vue emit vs
stayed a raw passthrough listener, see the [Events guide](/docs/learn/events/)
and the [Components API](/docs/api/components/).
