
Desarrollar una app móvil en React Native (Expo) capaz de conectarse a una API PHP que realiza operaciones CRUD sobre una tabla en MySQL, todo dentro de una red local.
MySQ: Base de datos
PHP (Apache o XAMPP): API en backend
React Native + ExpoApp: móvil frontend
Postman (opcional): Prueba de endpoints API
VS Code: Editor de código
Expo Go: Pruebas en el móvil (iOS/Android)
En phpMyAdmin o línea de comandos de MySQL:
CREATE DATABASE tienda;
USE tienda;
CREATE TABLE productos (
id INT AUTO_INCREMENT PRIMARY KEY,
nombre VARCHAR(100),
precio DECIMAL(10,2)
);
api/
├── conexion.php
├── obtener.php
├── crear.php
├── actualizar.php
├── eliminar.php
fichero conexion.php
<?php
$host = "localhost";
$user = "root";
$password = ""; // tu contraseña
$db = "tienda";
$conn = new mysqli($host, $user, $password, $db);
if ($conn->connect_error) {
die("Conexión fallida: " . $conn->connect_error);
}
?>
Fichero obtener.php
<?php
header("Access-Control-Allow-Origin: *");
header("Content-Type: application/json");
include "conexion.php";
$sql = "SELECT * FROM productos";
$result = $conn->query($sql);
$datos = [];
while ($fila = $result->fetch_assoc()) {
$datos[] = $fila;
}
echo json_encode($datos);
?>
fichero crear.php
<?php
header("Access-Control-Allow-Origin: *");
header("Content-Type: application/json");
include "conexion.php";
$input = json_decode(file_get_contents("php://input"), true);
$nombre = $input["nombre"];
$precio = $input["precio"];
$sql = "INSERT INTO productos (nombre, precio) VALUES ('$nombre', '$precio')";
if ($conn->query($sql)) {
echo json_encode(["mensaje" => "Producto creado"]);
} else {
echo json_encode(["mensaje" => "Error"]);
}
?>
fichero actualizar.php
<?php
header("Access-Control-Allow-Origin: *");
header("Content-Type: application/json");
include "conexion.php";
$input = json_decode(file_get_contents("php://input"), true);
$id = $input["id"];
$nombre = $input["nombre"];
$precio = $input["precio"];
$sql = "UPDATE productos SET nombre='$nombre', precio='$precio' WHERE id=$id";
if ($conn->query($sql)) {
echo json_encode(["mensaje" => "Producto actualizado"]);
} else {
echo json_encode(["mensaje" => "Error"]);
}
?>
fichero eliminar.php
<?php
header("Access-Control-Allow-Origin: *");
header("Content-Type: application/json");
include "conexion.php";
$input = json_decode(file_get_contents("php://input"), true);
$id = $input["id"];
$sql = "DELETE FROM productos WHERE id=$id";
if ($conn->query($sql)) {
echo json_encode(["mensaje" => "Producto eliminado"]);
} else {
echo json_encode(["mensaje" => "Error"]);
}
?>
Crear proyecto:
npx create-expo-app tiendaApp --template -blank
cd tiendaApp
npx expo start
Instala dependencias (opcional si usarás formularios o navegación):
npm install react-native-paper
Lectura + Formulario básico (App.js
import React, { useState, useEffect } from 'react';
import { View, Text, FlatList, TextInput, Button, StyleSheet } from 'react-native';
export default function App() {
const [productos, setProductos] = useState([]);
const [nombre, setNombre] = useState("");
const [precio, setPrecio] = useState("");
const API = "http://<TU_IP_LOCAL>/api";
const obtenerDatos = () => {
fetch(`${API}/obtener.php`)
.then(res => res.json())
.then(data => setProductos(data))
.catch(err => console.error(err));
};
const crearProducto = () => {
fetch(`${API}/crear.php`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ nombre, precio })
})
.then(res => res.json())
.then(() => {
obtenerDatos();
setNombre("");
setPrecio("");
});
};
const eliminarProducto = (id) => {
fetch(`${API}/eliminar.php`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ id })
})
.then(res => res.json())
.then(() => obtenerDatos());
};
useEffect(() => {
obtenerDatos();
}, []);
return (
<View style={styles.container}>
<Text style={styles.title}>Tienda</Text>
<FlatList
data={productos}
keyExtractor={item => item.id.toString()}
renderItem={({ item }) => (
<View style={styles.item}>
<Text>{item.nombre} - ${item.precio}</Text>
<Button title="Eliminar" onPress={() => eliminarProducto(item.id)} />
</View>
)}
/>
<TextInput placeholder="Nombre" value={nombre} onChangeText={setNombre} style={styles.input} />
<TextInput placeholder="Precio" value={precio} onChangeText={setPrecio} keyboardType="numeric" style={styles.input} />
<Button title="Crear producto" onPress={crearProducto} />
</View>
);
}
const styles = StyleSheet.create({
container: { padding: 20, marginTop: 40 },
title: { fontSize: 24, fontWeight: 'bold', marginBottom: 10 },
input: { borderWidth: 1, marginVertical: 5, padding: 8 },
item: { marginBottom: 10 }
});
Continua en:
Frexus
No comments yet