Buscar en tiempo real con React JS, PHP, MySQL y Bootstrap

Demo Github

El potencial de la librería React JS es que puedes crear los módulos que requieras, pero también es muy rápido para las consultas a la base de datos, no por algo es usado por Facebook.

Para los que no saben React JS es el framework javascript, usado en la Red Social más famosa del mundo “Facebook”.

Recalcar que React JS no tiene ni está hecho para MVC, pero puede interactuar con Angular JS y Backbone JS, para hacerlo MVC.

React JS usa la arquitectura FLUX:

Arquitectura FLUX usada por React
El Dispatcher en Flux no es solo un simple mediador; en realidad, es un cuello de botella centralizado diseñado a propósito

En este oportunidad les enseñare a como buscar un ítem en tiempo real con React JS, la información la jalo de mi Base de datos MySQL con PHP. (El buscador de FanPages, Amigos, Grupos, etc. de Facebook Usa esta tecnología para hacer las búsquedas.)

Web oficial de React
Su sitio web suele ser rediseñado cada cierto tiempo

1. Crear Tabla en MySQL (productos)

Creó una base de datos llamada test (la he creado desde phpMyAdmin para no complicarme) y dentro de ella creo una tabla llamada productos con la siguiente instrucción SQL:

CREATE TABLE productos (
    id INT AUTO_INCREMENT PRIMARY KEY,
    nombre VARCHAR(255) NOT NULL,
    precio DECIMAL(10,2) NOT NULL,
    stock INT NOT NULL
);

Con ello tenemos nuestra tabla productos con los campos, id, nombre, precio y stock.

2. Insertamos Datos de Prueba

Para que nuestra tabla productos no este vacía, le insertamos 5 postres o productos:

INSERT INTO productos (nombre, precio, stock) VALUES
('Pastel de Chocolate', 5.99, 10),
('Tarta de Fresas', 7.50, 8),
('Helado de Vainilla', 3.25, 15),
('Brownie', 4.75, 12),
('Galletas de Avena', 2.99, 20);

3. index.html (Para el frontend con React + Bootstrap)

Nota: Dejaré comentarios  en el código, para explicar que hace cada uno de ellos.

<!DOCTYPE html>
<html lang="es">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Demo: Buscar en tiempo real con React JS, PHP, MySQL y Bootstrap</title>
    
    <!-- Bootstrap 5 para el diseño -->
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
    
    <!-- React y ReactDOM desde CDNs para usar sin Node.js -->
    <script src="https://unpkg.com/react@18/umd/react.development.js"></script>
    <script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
    
    <!-- Babel para poder escribir JSX en este archivo -->
    <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
</head>
<body class="bg-light">
    <div class="container mt-4">
        <h1 class="text-center mb-4">Demo: Buscar en tiempo real con React JS, PHP, MySQL y Boostrap</h1>
        <div id="root"></div>
    </div>

    <script type="text/babel">
        function Search() {
            // Estados para manejar la búsqueda y los postres
            const [query, setQuery] = React.useState(""); // Guarda el texto del buscador
            const [postres, setPostres] = React.useState([]); // Guarda todos los postres desde la BD
            const [filteredPostres, setFilteredPostres] = React.useState([]); // Guarda los postres filtrados

            // Cargar los postres cuando se monta el componente
            React.useEffect(() => {
                fetch("buscar.php") // Llamamos al backend en PHP
                    .then(response => response.json())
                    .then(data => {
                        setPostres(data); // Guardamos todos los postres en el estado
                        setFilteredPostres(data); // Al inicio, mostramos todos los postres
                    });
            }, []);

            // Función para filtrar los postres en tiempo real
            const handleSearch = (e) => {
                const searchTerm = e.target.value.toLowerCase(); // Convertimos a minúsculas para evitar errores
                setQuery(searchTerm); // Guardamos la búsqueda en el estado

                // Filtramos los postres sin hacer más peticiones al servidor
                const filtered = postres.filter(postre =>
                    postre.nombre.toLowerCase().includes(searchTerm)
                );

                setFilteredPostres(filtered); // Actualizamos la lista filtrada
            };

            return (
                <div className="card shadow p-4">
                    {/* Input para escribir el texto de búsqueda */}
                    <input 
                        type="text" 
                        className="form-control mb-3"
                        placeholder="Ingrese el Nombre del Postre que desea Buscar" 
                        value={query} 
                        onChange={handleSearch} // Se ejecuta cada vez que el usuario escribe
                    />
                    
                    {/* Tabla donde se listan los postres */}
                    <div className="table-responsive">
                        <table className="table table-bordered table-hover">
                            <thead className="table-dark">
                                <tr>
                                    <th>ID</th>
                                    <th>Nombre</th>
                                    <th>Precio</th>
                                    <th>Stock</th>
                                </tr>
                            </thead>
                            <tbody>
                                {/* Si hay postres filtrados, los mostramos en la tabla */}
                                {filteredPostres.length > 0 ? (
                                    filteredPostres.map((postre) => (
                                        <tr key={postre.id}>
                                            <td>{postre.id}</td>
                                            <td>{postre.nombre}</td>
                                            <td>${postre.precio}</td>
                                            <td>{postre.stock}</td>
                                        </tr>
                                    ))
                                ) : (
                                    // Si no hay resultados, mostramos un mensaje en la tabla
                                    <tr>
                                        <td colSpan="4" className="text-center">No se encontraron resultados</td>
                                    </tr>
                                )}
                            </tbody>
                        </table>
                    </div>
                </div>
            );
        }

        // Renderizamos el componente en el div con id "root"
        ReactDOM.createRoot(document.getElementById("root")).render(<Search />);
    </script>
</body>
</html>

4. buscar.php (Este es el backend de PHP)

Ahora en nuestro archivo buscar.php conectamos a la Base de Datos MySQL y llamamos a los registros:

<?php
    // Permite que cualquier dominio pueda acceder a la API (CORS)
    header("Access-Control-Allow-Origin: *");

    // Indicamos que la respuesta será en formato JSON
    header("Content-Type: application/json");

    // Datos de conexión a la base de datos
    $servername = "localhost"; // Servidor (localhost si es en local)
    $username = "root"; // Usuario de MySQL
    $password = ""; // Contraseña de MySQL
    $dbname = "nombre-de-tu-bd"; // Nombre de la base de datos

    // Conectamos a la base de datos
    $conn = new mysqli($servername, $username, $password, $dbname);

    // Verificamos si la conexión falló
    if ($conn->connect_error) {
        die("Conexión fallida: " . $conn->connect_error);
    }

    // Consulta para obtener todos los postres de la tabla "productos"
    $sql = "SELECT * FROM productos";
    $result = $conn->query($sql);

    // Creamos un array para almacenar los postres
    $postres = [];

    // Recorremos los resultados y los agregamos al array
    while ($row = $result->fetch_assoc()) {
        $postres[] = $row;
    }

    // Convertimos el array en formato JSON y lo enviamos como respuesta
    echo json_encode($postres);

    // Cerramos la conexión a la base de datos
    $conn->close();
?>

Listo, eso es todo.

Si abrimos nuestro archivo index.html en el navegador podemos ver que el buscador funciona:

Buscador en Tiempo Real que funciona con React JS, PHP, MySQL y Bootstrap
La búsqueda la realiza por nombre, pero puedes configurarlo para que también busque por otros campos

Si deseas, le puedes agregar una columna más y la llamas acciones y allí colocas los botones, editar, eliminar y también en la parte superior colocan un botón, agregar nuevo ítem y que les habrá un popup Bootstrap y tendrás un CRUD.

Síguenos en las Redes Sociales para que no te pierdas nuestros próximos contenidos.