# React guide

> How to write SymbioteNative apps with the React adapter.

The React adapter is the most familiar entry point if you already know React
Native. It exposes React components and callback props, but it commits through
SymbioteNative's shared engine instead of React Native's own Fabric host config.

## Minimal component

```tsx
import './App.css';
import { useState } from 'react';

export default function App() {
  const [count, setCount] = useState(0);
  const [pressed, setPressed] = useState(false);

  return (
    <view className="root">
      <pressable
        onPress={() => setCount(value => value + 1)}
        onPressIn={() => setPressed(true)}
        onPressOut={() => setPressed(false)}
      >
        <text className={pressed ? 'pressed' : 'label'}>Count is {count}</text>
      </pressable>
    </view>
  );
}
```

`view`, `pressable`, and `text` are intrinsic tags — no import needed. Only a
composed component (`FlatList`, `SectionList`, `VirtualizedList`,
`VirtualizedSectionList`, `KeyboardAvoidingView`, hooks, …) still comes from
`@symbiote-native/react`.

```css
/* App.css */
.root {
  flex: 1;
  align-items: center;
  justify-content: center;
}
.label {
  font-size: 24px;
}
.pressed {
  font-size: 24px;
  opacity: 0.6;
}
```

`StyleSheet.create` works identically if you'd rather keep style objects
inline instead of a CSS file — see the [Styling guide](/docs/learn/styling/)
for both paths.

## React contract

React uses the React Native-style surface:

- events are callback props like `onPress` and `onValueChange` (shared by
  `Switch` and `TextInput`, both firing with the native event as a second
  argument — `TextInput`'s is `(text, event)`, `Switch`'s is `(value, event)`);
- press state is not a render prop: `pressable` is a host tag, so mirror it into
  local state off `onPressIn`/`onPressOut`, or take it from a functional
  `style={({ pressed }) => …}`;
- render functions stay where a framework element is genuinely the return value,
  for example `FlatList`'s `renderItem`;
- imperative APIs use React refs, for example `ref.current?.focus()` on
  `TextInput`;
- app code imports from `@symbiote-native/react`, while the consuming app still pins
  `react` and `react-native` at the top level.

## What SymbioteNative owns

React still owns hooks, component state, and render scheduling. The adapter owns
only the host bridge: it maps React reconciler mutations to `@symbiote-native/engine`.
The engine then translates those mutations into Fabric's persistent commit model.

Read the exact API surface in the [React API reference](/docs/api/react/).
