Skip to Content
Examples11 · React Native

11 · React Native

3va can’t render React Native: that needs the native bridge and Metro. Much of an RN app is plain TypeScript, though: reducers, selectors, form validation, formatting, the API client. 3va runs and tests that part directly, and the same modules can be shared with a backend.

Source: examples/11-react-native

src/ todos.ts todo-list reducer + selectors (pure TS) validate.ts signup form validation (shared with the backend) index.ts runnable demo todos.test.ts Jest-compatible tests

Run the demo

cd examples/11-react-native 3va run src/index.ts --allow-read=./src
=== Lógica compartida React Native, ejecutada con 3va === Tareas: 3 [x] Revisar el PR de auth [ ] Diseñar el onboarding [ ] Actualizar iconos Progreso: ███░░░░░░░ 33% (1/3) Creadas en el último minuto: 3 Errores de validación del formulario de registro: email: Email no válido password: Mínimo 8 caracteres confirmPassword: Las contraseñas no coinciden

(The example’s strings are in Spanish.) The demo dispatches four add actions, one of them blank (" "), which the reducer ignores, so there are 3 tasks. Then it toggles the first one.

Run the tests

3va test
✓ todoReducer > agrega una tarea limpia (trim) y asigna id ✓ todoReducer > ignora tareas vacías ✓ todoReducer > toggle marca/desmarca una tarea ✓ todoReducer > remove elimina la tarea exacta ✓ todoReducer > clear-done elimina solo las completadas ✓ selectProgress / prettyProgress > progreso 50% con una de dos hecha ✓ selectProgress / prettyProgress > prettyProgress dibuja la barra y el conteo ✓ validateSignup > email inválido ✓ validateSignup > password débil ✓ validateSignup > contraseñas que no coinciden Tests: 10 Passed: 10

How it works

The reducer is an ordinary pure function over a discriminated union, the same kind of code you’d pass to useReducer in a component:

src/todos.ts
export type TodoAction = | { type: "add"; text: string } | { type: "toggle"; id: string } | { type: "remove"; id: string } | { type: "clear-done" }; export function todoReducer(state: Todo[], action: TodoAction): Todo[] { … }

It imports nothing from react-native, so 3va can load it. The component calls useReducer(todoReducer, []), and a test calls todoReducer directly.

In a real React Native project

npx react-native run-android # native build + Metro: still RN's own tooling 3va install # dependencies (no postinstall scripts) 3va run scripts/generate-types.ts # codegen / config scripts 3va test # the Jest suite for your pure logic

Things to keep in mind

  • Only modules with no native imports can run. Anything that imports react-native, expo-* native modules, or NativeModules won’t run under 3va. Keep business logic in separate files that don’t import those, which is good design anyway.
  • --allow-read=./src is needed for 3va run because index.ts imports ./todos and ./validate. Without it: Permission denied: --allow-read=…/src/todos.ts is required. 3va test didn’t need it.
  • Your existing Jest setup doesn’t carry over. jest.config.js, preset: "react-native", jest.mock(...) of native modules and @testing-library/react-native component tests belong in the RN Jest setup. Use 3va test for the pure-logic suite.
  • Time-dependent code: selectDueSoon and the ID generator use Date.now(). The tests avoid asserting exact IDs and timestamps. Do the same, or inject the clock.