# 使用 React 连接到部署

本文主要介绍如何在 React 项目中使用 MQTT (opens new window),实现客户端与 MQTT 服务器的连接、订阅、收发消息、取消订阅等功能。

React 是一款用于构建用户界面的开源 JavaScript 库。React 视图通常采用包含以自定义 HTML 规定的其他组件的组件渲染。React 为程序员提供了一种子组件不能直接影响外层组件("data flows down")的模型,数据改变时对视图进行了有效更新,实现了在现代单页应用中组件之间的干净分离。由于 React 的设计思想极其独特,属于革命性创新,性能出众,代码逻辑却非常简单。所以,越来越多的人开始关注和使用,目前是 Web 开发的主流工具之一。

React 起源于 Facebook 的内部项目,目前由 Facebook 企业和其强大的开源社区进行维护。React 目前正在被 Netflix、Instagram、Imgur、Airbnb 等很多知名网站的主页使用。该框架首先于 2011 年部署于 Facebook 的 newsfeed,随后于 2012 年部署于 Instagram。在 2013 年 5 月在 JSConf US 开源。

# 前提条件

  1. 已经创建了部署,在 部署概览 下可以查看到连接相关的信息,请确保部署状态为运行中。同时你可以使用 WebSocket 测试连接到 MQTT 服务器。
  2. 认证鉴权 > 认证 中设置用户名和密码,用于连接验证。

# 新建项目

参考链接:https://zh-hans.reactjs.org/docs/getting-started.html (opens new window)

  • 使用 Create React App 创建新的 React 应用

    npx create-react-app react-mqtt-test
    
    1

    如需使用 TypeScript 只需要在命令行后加入 --template typescript 参数即可

    npx create-react-app react-mqtt-test --template typescript
    
    1

    然后添加 React 项目中需要的 TypeScript 的类型库

    npm install --save typescript @types/node @types/react @types/react-dom @types/jest
    # or
    yarn add typescript @types/node @types/react @types/react-dom @types/jest
    
    1
    2
    3

    使用 TypeScript 将不作为本文示例中的使用重点介绍,如需使用,可参考该创建示例和完整的代码示例后自行添加 TypeScript 特性。

  • 使用 CDN 链接引入 React

    <script crossorigin src="https://unpkg.com/react@16/umd/react.production.min.js"></script>
    <script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"></script>
    
    1
    2

# 安装 MQTT 客户端库

因为 React 是一款 JavaScript 库,因此可以使用 MQTT.js 作为 MQTT 客户端库。

以下 2,3 方法更适用于通过 CDN 链接 引用 React 创建的项目。

  1. 通过命令行安装,可以使用 npm 或 yarn 命令(二者选一)

    npm install mqtt --save
    # or
    yarn add mqtt
    
    1
    2
    3
  2. 通过 CDN 引入

    <script src="https://unpkg.com/mqtt/dist/mqtt.min.js"></script>
    
    1
  3. 下载到本地,然后使用相对路径引入

    <script src="/your/path/to/mqtt.min.js"></script>
    
    1

# 连接

请在控制台的 部署概览 找到相关的地址以及端口信息,需要注意如果是基础版,端口不是 1883 或 8883 端口,请确认好端口。

# 连接设置

本文将使用 EMQX 提供的 免费公共 MQTT 服务器 (opens new window),该服务基于 EMQX 的 MQTT 物联网云平台 (opens new window) 创建。服务器接入信息如下:

  • Broker: broker.emqx.io(国内可以使用 broker-cn.emqx.io)
  • TCP Port: 1883
  • WebSocket Port: 8083

# 连接代码

const [client, setClient] = useState(null);
const mqttConnect = (host, mqttOption) => {
  setConnectStatus("Connecting");
  setClient(mqtt.connect(host, mqttOption));
};
useEffect(() => {
  if (client) {
    console.log(client);
    client.on("connect", () => {
      setConnectStatus("Connected");
    });
    client.on("error", (err) => {
      console.error("Connection error: ", err);
      client.end();
    });
    client.on("reconnect", () => {
      setConnectStatus("Reconnecting");
    });
    client.on("message", (topic, message) => {
      const payload = { topic, message: message.toString() };
      setPayload(payload);
    });
  }
}, [client]);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

# 订阅主题

const mqttSub = (subscription) => {
  if (client) {
    const { topic, qos } = subscription;
    client.subscribe(topic, { qos }, (error) => {
      if (error) {
        console.log("Subscribe to topics error", error);
        return;
      }
      setIsSub(true);
    });
  }
};
1
2
3
4
5
6
7
8
9
10
11
12

# 取消订阅

const mqttUnSub = (subscription) => {
  if (client) {
    const { topic } = subscription;
    client.unsubscribe(topic, (error) => {
      if (error) {
        console.log("Unsubscribe error", error);
        return;
      }
      setIsSub(false);
    });
  }
};
1
2
3
4
5
6
7
8
9
10
11
12

# 消息发布

const mqttPublish = (context) => {
  if (client) {
    const { topic, qos, payload } = context;
    client.publish(topic, payload, { qos }, (error) => {
      if (error) {
        console.log("Publish error: ", error);
      }
    });
  }
};
1
2
3
4
5
6
7
8
9
10

# 断开连接

const mqttDisconnect = () => {
  if (client) {
    client.end(() => {
      setConnectStatus("Connect");
    });
  }
};
1
2
3
4
5
6
7

完整项目示例代码:https://github.com/emqx/MQTT-Client-Examples/tree/master/mqtt-client-React (opens new window)

# 测试

我们使用 React 编写了如下简单的浏览器应用,该应用具备:创建连接、订阅主题、收发消息、取消订阅、断开连接等功能。

reactmqttpage.png

使用 MQTT 5.0 客户端工具 - MQTT X (opens new window) 作为另一个客户端进行消息收发测试。

reactmqttx.png

可以看到 MQTT X 可以正常接收来自浏览器端发送的消息,同样,使用 MQTT X 向该主题发送一条消息时,也可以看到浏览器端可以正常接收到该消息。

reactmqtttest.png

# 更多内容

综上所述,我们实现了在 React 项目中创建 MQTT 连接,模拟了客户端与 MQTT 服务器进行订阅、收发消息、取消订阅以及断开连接的场景。

本文使用的 React 版本为 v16.13.1,因此将使用 Hook Component 特性来作为示例代码演示,如有需求也可参考完整的示例代码中的 ClassMqtt 组件来使用 Class Component 特性来进行项目构建。

可以在 这里 (opens new window) 下载到示例的源码,同时也可以在 GitHub (opens new window) 上找到更多其他语言的 Demo 示例。