# MQTT + React: Building IoT Dashboards with Live Sensor Data
By Govind Bajaj · 2025

Tags: mqtt, iot, react, dashboard, sensors
I connected 47 temperature sensors to a React dashboard using MQTT. Data flows from sensor to screen in 200ms. Here's the complete pipeline from hardware to UI.
I connected forty-seven temperature sensors to a React dashboard using MQTT last quarter.

Data flows from the physical sensor to the screen in approximately two hundred milliseconds. The dashboard shows a warehouse floor plan with live temperature readings, color-coded from blue (cold) to red (hot). Alerts fire when any zone exceeds its threshold. And the entire system runs on a $5/month MQTT broker.

Here is the complete pipeline from hardware to UI.

## Why MQTT for IoT

MQTT is a lightweight publish-subscribe protocol designed for unreliable networks and low-bandwidth environments. It uses a broker-based model where devices publish to topics and clients subscribe to receive updates.

Compared to WebSockets or HTTP polling, MQTT has three advantages for IoT. It is extremely lightweight with only 2 bytes of overhead per message. It handles intermittent connections gracefully with configurable QoS levels and last-will messages. And it scales efficiently with one broker handling millions of connections.

## The Architecture

The sensor publishes temperature readings to a topic like temp/warehouse/zone-01. The MQTT broker receives and routes the message. A Node.js backend subscribes to all temp topics, stores readings in MongoDB, and forwards them to the React dashboard via WebSocket.

## The Sensor Side (ESP32)

```cpp
#include <WiFi.h>
#include <PubSubClient.h>

const char* mqtt_server = "broker.hivemq.com";
const char* topic = "temp/warehouse/zone-01";
const char* sensorId = "zone-01";

void loop() {
  float temperature = readTemperature();
  
  String payload = "{";
  payload += "\"sensorId\":\"" + String(sensorId) + "\",";
  payload += "\"temperature\":" + String(temperature);
  payload += "}";
  
  client.publish(topic, payload.c_str(), true);
  delay(5000);
}
```

The retained flag (true) means the broker keeps the last message. When the dashboard connects, it immediately receives the most recent reading instead of waiting for the next sensor publish.

## The Backend: MQTT to MongoDB to WebSocket

```ts
import mqtt from "mqtt"
import { Server } from "socket.io"

const client = mqtt.connect(process.env.MQTT_BROKER_URL)

client.on("connect", () => {
  client.subscribe("temp/warehouse/#")
})

client.on("message", async (topic, message) => {
  const data = JSON.parse(message.toString())
  
  await Reading.create({
    sensorId: data.sensorId,
    temperature: data.temperature,
    timestamp: new Date(),
    topic,
  })
  
  io.emit("sensor-reading", {
    sensorId: data.sensorId,
    temperature: data.temperature,
    zone: topic.split("/").pop(),
  })
})
```

## The React Dashboard

```tsx
import { useEffect, useState } from "react"
import { io } from "socket.io-client"

export function TemperatureDashboard() {
  const [readings, setReadings] = useState({})
  
  useEffect(() => {
    const socket = io(process.env.NEXT_PUBLIC_SOCKET_URL)
    socket.on("sensor-reading", (data) => {
      setReadings(prev => ({ ...prev, [data.sensorId]: data }))
    })
    return () => socket.disconnect()
  }, [])
  
  return (
    <div className="grid grid-cols-4 gap-4">
      {Object.values(readings).map(sensor => (
        <SensorCard key={sensor.sensorId} sensor={sensor} />
      ))}
    </div>
  )
}
```

## QoS Levels: When Reliability Matters

MQTT has three Quality of Service levels:

QoS 0 (at most once): Fire and forget. Fastest, but messages may be lost. Use for non-critical telemetry where occasional loss is acceptable.

QoS 1 (at least once): Message is guaranteed to arrive, but may be duplicated. Good for important alerts where duplication is better than loss.

QoS 2 (exactly once): Guaranteed delivery with no duplicates. Slowest, use only for critical commands.

For temperature readings, I use QoS 0. For alert thresholds, I use QoS 1.

## Takeaways

- MQTT is purpose-built for IoT: lightweight, broker-based, handles unreliable networks
- Use retained messages so new subscribers get the last reading immediately
- The backend bridges MQTT to WebSocket — sensors speak MQTT, browsers speak WebSocket
- QoS 0 for telemetry, QoS 1 for alerts, QoS 2 only for critical commands
- Store all readings in MongoDB for historical analysis and trend detection
- A $5/month MQTT broker handles thousands of sensors
- The hard part is reliable sensor hardware and network connectivity in industrial environments