Habilidades imprescindibles para un desarrollador de React Native

Habilidades imprescindibles para un desarrollador de React Native

React Native permite crear apps para iOS y Android con JavaScript y React. Este repaso cubre las habilidades que necesita un desarrollador para trabajar con calidad, desde los tipos hasta el despliegue continuo.

1. TypeScript

Definición: Sistema de tipos estático sobre JavaScript. En React Native ayuda a detectar errores antes de ejecutar la app.

Ejemplo real: Definir la forma de un producto y las props de una tarjeta.

type Producto = {
  id: string;
  nombre: string;
  precio: number;
};

type Props = {
  producto: Producto;
  onAgregar: (id: string) => void;
};

export default function TarjetaProducto({ producto, onAgregar }: Props) {
  return (
    <Pressable onPress={() => onAgregar(producto.id)}>
      <Text>{producto.nombre}</Text>
    </Pressable>
  );
}

Idea clave: TypeScript evita que una propiedad mal escrita llegue a producción.

2. Hooks

Definición: Funciones que permiten usar estado y ciclo de vida dentro de componentes funcionales.

Ejemplo real: Cargar productos al abrir la pantalla y recargar al volver a ella con useFocusEffect de React Navigation.

const [productos, setProductos] = useState<Producto[]>([]);

useEffect(() => {
  cargarProductos();
}, []);

useFocusEffect(
  useCallback(() => {
    if (hayCambios) {
      cargarProductos();
    }
  }, [hayCambios])
);

Idea clave: useState y useEffect manejan el estado local. useFocusEffect responde a la navegación, algo típico de móvil.

3. Redux

Definición: Contenedor centralizado de estado de la app. En proyectos React Native suele usarse con Redux Toolkit.

Ejemplo real: Un carrito de compras compartido por varias pantallas.

const carritoSlice = createSlice({
  name: 'carrito',
  initialState: [] as Producto[],
  reducers: {
    agregar: (state, action: PayloadAction<Producto>) => {
      state.push(action.payload);
    },
    quitar: (state, action: PayloadAction<string>) => {
      return state.filter((p) => p.id !== action.payload);
    },
  },
});

export const { agregar, quitar } = carritoSlice.actions;
export default carritoSlice.reducer;

Idea clave: Redux conviene cuando el estado se comparte entre muchas pantallas. Para estado local, los Hooks bastan.

4. REST APIs

Definición: Interfaces HTTP que exponen recursos con verbos como GET, POST, PUT y DELETE.

Ejemplo real: Traer la lista de productos desde un servidor.

export async function obtenerProductos(): Promise<Producto[]> {
  const respuesta = await fetch('https://api.ejemplo.com/productos');
  if (!respuesta.ok) {
    throw new Error(`Error HTTP ${respuesta.status}`);
  }
  return respuesta.json();
}

Idea clave: Siempre revisa respuesta.ok y envuelve la llamada en try/catch. En móvil, piensa además en la conexión lenta o ausente.

5. async/await y Promises

Definición: Forma de escribir código asíncrono de manera secuencial sobre Promises.

Ejemplo real: Cargar productos y categorías en paralelo para no bloquear la interfaz.

const cargarPantalla = async () => {
  setCargando(true);
  try {
    const [productos, categorias] = await Promise.all([
      obtenerProductos(),
      obtenerCategorias(),
    ]);
    setProductos(productos);
    setCategorias(categorias);
  } catch (error) {
    setError('No se pudieron cargar los datos');
  } finally {
    setCargando(false);
  }
};

Idea clave: await espera sin congelar la interfaz. Promise.all ejecuta en paralelo y finally libera el indicador de carga.

6. GraphQL

Definición: Lenguaje de consulta que pide solo los campos que la pantalla necesita.

Ejemplo real: Pedir id, nombre y precio de productos filtrados por categoría.

const OBTENER_PRODUCTOS = gql`
  query ObtenerProductos($categoria: String) {
    productos(categoria: $categoria) {
      id
      nombre
      precio
    }
  }
`;

const { data, loading, error } = useQuery(OBTENER_PRODUCTOS, {
  variables: { categoria: 'electronica' },
});

Idea clave: GraphQL reduce el tráfico de datos con Apollo Client. Conviene cuando varias pantallas necesitan campos distintos del mismo recurso.

7. Firebase

Definición: Plataforma de Google que ofrece autenticación, base de datos, almacenamiento y analítica.

Ejemplo real: Guardar una venta en Firestore tras el pago.

import { getAuth, signInAnonymously } from 'firebase/auth';
import {
  getFirestore,
  collection,
  addDoc,
  getDocs,
} from 'firebase/firestore';

const auth = getAuth();
const db = getFirestore();

await signInAnonymously(auth);
await addDoc(collection(db, 'ventas'), {
  productoId: '123',
  fecha: new Date().toISOString(),
});
const ventas = await getDocs(collection(db, 'ventas'));

Idea clave: Firebase acelera el arranque de una app móvil. La configuración va en un archivo de entorno, nunca en el código.

8. Testing

Definición: Pruebas automatizadas que verifican que los componentes y la lógica hacen lo esperado.

Ejemplo real: Probar que un botón muestra el producto y responde al toque.

import { render, screen, fireEvent } from '@testing-library/react-native';
import BotonAgregar from './BotonAgregar';

test('muestra el nombre y responde al toque', () => {
  const onAgregar = jest.fn();
  render(
    <BotonAgregar
      producto={{ id: '1', nombre: 'Teclado', precio: 99 }}
      onAgregar={onAgregar}
    />
  );
  expect(screen.getByText('Teclado')).toBeTruthy();
  fireEvent.press(screen.getByText('Agregar'));
  expect(onAgregar).toHaveBeenCalledWith('1');
});

Idea clave: Jest es el runner por defecto de React Native. Prueba pantallas, lógica de negocio y casos límite.

9. Git y CI/CD

Definición: Git controla el historial del código. CI/CD construye, prueba y publica la app de forma automática.

Ejemplo real: Un workflow que ejecuta lint, pruebas y compila para Android con EAS Build.

name: Build Android
on:
  push:
    branches: [main]
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 20
      - run: npm ci
      - run: npm run lint
      - run: npm test -- --run
      - uses: expo/expo-github-action@v8
        with:
          eas-version: latest
      - run: eas build --platform android --non-interactive

Idea clave: Rama principal protegida, ramas por función y compilación automática en cada envío.

10. SonarQube

Definición: Servidor de inspección continua que mide calidad del código: bugs, vulnerabilidades, deuda técnica y cobertura.

Ejemplo real: Configurar el proyecto para que el pipeline suba el informe.

sonar.projectKey=rn-miapp
sonar.projectName=MiApp React Native
sonar.sources=src
sonar.tests=src/__tests__
sonar.test.inclusions=src/__tests__/**/*.test.tsx
sonar.javascript.lcov.reportPaths=coverage/lcov.info

Idea clave: SonarQube convierte la calidad en una puerta del pipeline: si hay errores bloqueantes, la compilación falla.

11. Navegación y arquitectura mobile

Definición: React Navigation gestiona pilas, pestañas y drawers. La arquitectura mobile organiza pantallas, componentes y lógica por responsabilidades.

Ejemplo real: Una pila tipada con parámetros seguros.

export type RootStackParamList = {
  Inicio: undefined;
  Detalle: { productoId: string };
};

const Stack = createNativeStackNavigator<RootStackParamList>();

const navegacion =
  useNavigation<NativeStackNavigationProp<RootStackParamList>>();

navegacion.navigate('Detalle', { productoId: 'abc' });

Idea clave: Tipar los parámetros evita navegar con datos faltantes. Separa la UI de la lógica con un patrón de contenedores y presentación.

12. Integración con código nativo iOS/Android

Definición: React Native permite escribir módulos en Swift, Objective-C, Kotlin o Java y exponerlos a JavaScript.

Ejemplo real: Leer el nivel de batería desde Android con un módulo nativo.

class BatteryModule(reactContext: ReactApplicationContext) :
  ReactContextBaseJavaModule(reactContext) {
  override fun getName() = "BatteryModule"

  @ReactMethod
  fun getBatteryLevel(promise: Promise) {
    val manager =
      reactContext.getSystemService(BatteryManager::class.java)
    promise.resolve(
      manager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY)
    )
  }
}
import { NativeModules } from 'react-native';

const nivel = await NativeModules.BatteryModule.getBatteryLevel();

Idea clave: Cuando una capacidad del dispositivo no existe en JavaScript, el módulo nativo es el camino. Con Expo, usa expo-modules-core para no mantener el código nativo a mano.

Para recordar

Un desarrollador de React Native combina tipos, estado, datos, calidad y despliegue. Las bases son TypeScript y Hooks. El resto se añade según la app: Redux para estado compartido, REST o GraphQL para datos, Firebase para backend rápido, testing y SonarQube para calidad, y CI/CD para entregar.

© Arturo Juárez Monroy