使用 React、Socket.io 和 Push Notifications 构建实时事件警报系统 🚀
这篇文章是关于什么的?
您希望一旦发生某件事,每个人都能在您的网站上收到消息。
这可以是新版本、公告或一些产品更新。
在本文中,我将指导您使用 React 和 Socket.io 构建一个事件调度系统。该应用程序允许用户为即将发生的事件设置提醒,并在事件发生时显示一个提示框。
Toaster = 屏幕上带有通知的小框。
有多种方法可以从服务器获取有关新事件的实时信息:
-
使用长轮询 HTTP 请求,基本上每 10 - 30 秒发送一次 HTTP 请求来获取有关新事件的信息。
-
当新的出价到达时,使用开放套接字(Websockets)直接从服务器获取信息。
在本文中,我将讨论 Websockets,特别是 Node.js 库 - Socket.io
Socket.io 是一个流行的 JavaScript 库,它允许我们在 Web 浏览器和 Node.js 服务器之间创建实时的双向通信。它是一个高性能且可靠的库,经过优化,能够以最小的延迟处理大量数据。它遵循 WebSocket 协议,并提供更强大的功能,例如回退到 HTTP 长轮询或自动重新连接,这使我们能够构建高效的实时应用程序。
Novu——第一个开源通知基础设施
简单介绍一下我们。Novu 是第一个开源通知基础设施。我们主要负责管理所有产品通知。通知可以是应用内通知(类似于开发者社区的Websockets中的铃铛图标)、电子邮件、短信等等。
如果你能给我们一颗星,我会非常高兴!这会帮助我每周写更多文章🚀
https://github.com/novuhq/novu
将 Socket.Io 与 React 连接起来😎
在这里,我们将为事件调度系统搭建项目环境。您还将学习如何将 Socket.io 添加到 React 和 Node.js 应用程序中,以及如何通过 Socket.io 连接两个开发服务器进行实时通信。
创建包含两个名为客户端和服务器的子文件夹的项目文件夹。
mkdir event-scheduler
cd event-scheduler
mkdir client server
通过终端导航到客户端文件夹并创建一个新的 React.js 项目。
cd client
npx create-react-app ./
安装 Socket.io 客户端 API 和 React Router。React Router 是一个 JavaScript 库,它使我们能够在 React 应用程序中的页面之间导航。
npm install socket.io-client react-router-dom
从 React 应用中删除多余的文件(例如徽标和测试文件),并更新App.js
文件以显示如下所示的 Hello World。
function App() {
return (
<div>
<p>Hello World!</p>
</div>
);
}
export default App;
导航到服务器文件夹并创建一个package.json
文件。
cd server & npm init -y
安装 Express.js、CORS、Nodemon 和 Socket.io 服务器 API。
Express.js 是一个快速、简约的框架,它提供了多种用于在 Node.js 中构建 Web 应用程序的功能。CORS 是一个 Node.js包 ,允许不同域之间进行通信。
Nodemon 是一个 Node.js 工具,它在检测到文件更改后会自动重启服务器,而 Socket.io 允许我们在服务器上配置实时连接。
npm install express cors nodemon socket.io
创建一个index.js
文件——Web 服务器的入口点。
touch index.js
使用 Express.js 设置一个简单的 Node.js 服务器。下面的代码片段会在浏览器中访问时返回一个 JSON 对象http://localhost:4000/api
。
//index.js
const express = require("express");
const app = express();
const PORT = 4000;
app.use(express.urlencoded({ extended: true }));
app.use(express.json());
app.get("/api", (req, res) => {
res.json({
message: "Hello world",
});
});
app.listen(PORT, () => {
console.log(`Server listening on ${PORT}`);
});
导入 HTTP 和 CORS 库以允许客户端和服务器域之间进行数据传输。
const express = require("express");
const app = express();
const PORT = 4000;
app.use(express.urlencoded({ extended: true }));
app.use(express.json());
//New imports
const http = require("http").Server(app);
const cors = require("cors");
app.use(cors());
app.get("/api", (req, res) => {
res.json({
message: "Hello world",
});
});
http.listen(PORT, () => {
console.log(`Server listening on ${PORT}`);
});
接下来,将 Socket.io 添加到项目中,以创建实时连接。在app.get()
代码块之前,复制以下代码。接下来,将 Socket.io 添加到项目中,以创建实时连接。在app.get()
代码块之前,复制以下代码。
//New imports
.....
const socketIO = require('socket.io')(http, {
cors: {
origin: "http://localhost:3000"
}
});
//Add this before the app.get() block
socketIO.on('connection', (socket) => {
console.log(`⚡: ${socket.id} user just connected!`);
socket.on('disconnect', () => {
console.log('🔥: A user disconnected');
});
});
从上面的代码片段中,该socket.io("connection")
函数与 React 应用程序建立连接,然后为每个套接字创建一个唯一的 ID,并在用户访问网页时将该 ID 记录到控制台。
当您刷新或关闭网页时,套接字会触发断开事件,表明用户已与套接字断开连接。
通过将启动命令添加到package.json
文件中的脚本列表中来配置 Nodemon。下面的代码片段使用 Nodemon 启动服务器。
//In server/package.json
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "nodemon index.js"
},
您现在可以使用以下命令通过 Nodemon 运行服务器。
npm start
打开App.js
客户端文件夹中的文件并将 React 应用程序连接到 Socket.io 服务器。
import socketIO from "socket.io-client";
const socket = socketIO.connect("http://localhost:4000");
function App() {
return (
<div>
<p>Hello World!</p>
</div>
);
}
export default App;
启动 React.js 服务器。
npm start
检查服务器运行的终端;React.js 客户端的 ID 应该出现在终端上。
恭喜🥂,React 应用程序已成功通过 Socket.io 连接到服务器。
应用程序界面📲
在本节中,我将指导您构建事件调度系统的用户界面。它是一个单页应用程序,包含三个组件:数字时钟、用于创建事件调度的表单字段以及列出即将发生的事件的部分。
更新App.js
文件如下:
import React from "react";
import Clock from "./components/Clock";
import CreateSchedule from "./components/CreateSchedule";
import Schedules from "./components/Schedules";
import socketIO from "socket.io-client";
const socket = socketIO.connect("http://localhost:4000");
const App = () => {
return (
<div className='app__container'>
<Clock />
<CreateSchedule />
<Schedules />
</div>
);
};
export default App;
导航到src/index.css
文件并复制以下代码。它包含设计此项目所需的所有 CSS。
@import url("https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@300;400;500;600;700&display=swap");
* {
box-sizing: border-box;
font-family: "Space Grotesk", sans-serif;
}
body {
margin: 0;
padding: 0;
}
.app__container {
display: flex;
flex-direction: column;
width: 100%;
min-height: 100vh;
padding: 30px;
}
.clock__container {
width: 100%;
display: flex;
align-items: center;
justify-content: center;
height: 20vh;
background-color: #f0ebe3;
margin-bottom: 30px;
}
.clock {
font-size: 50px;
color: #576f72;
}
.createSchedule__container {
margin-bottom: 30px;
width: 70%;
}
form div {
margin-bottom: 20px;
}
input {
margin-left: 20px;
padding: 5px;
width: 100px;
}
#title {
width: 70%;
}
button {
width: 200px;
padding: 15px;
font-size: 16px;
border: none;
outline: none;
background-color: #576f72;
color: #fff;
cursor: pointer;
}
时钟组件⏰
将代码复制到Clock.js
文件中以显示当前时间。
import React, { useState, useEffect } from "react";
const Clock = () => {
const [date, setDate] = useState(new Date());
const refreshClock = () => setDate(new Date());
useEffect(() => {
const timerId = setInterval(refreshClock, 1000);
return () => clearInterval(timerId);
}, []);
return (
<div className='clock__container'>
<h2 className='clock'>{date.toLocaleTimeString()}</h2>
</div>
);
};
export default Clock;
构建 Schedule 组件📅
将以下代码复制到CreateSchedule.js
文件中。它会显示一个表单,允许用户设置事件的时间和标题。
import React, { useState } from "react";
const CreateSchedule = () => {
const [hour, setHour] = useState(0);
const [minute, setMinute] = useState(0);
const [title, setTitle] = useState("");
const handleSubmit = (e) => {
e.preventDefault();
console.log({ hour, minute, title });
setHour("");
setMinute("");
setTitle("");
};
return (
<div className='createSchedule__container'>
<h2>Create a Schedule</h2>
<form onSubmit={handleSubmit}>
<div className='title__container'>
<label htmlFor='title'>Title</label>
<input
type='text'
name='title'
id='title'
value={title}
required
onChange={(e) => setTitle(e.target.value)}
/>
</div>
<div>
<label htmlFor='hour'>Select Hour</label>
<input
type='number'
min={0}
max={23}
name='hour'
id='hour'
value={hour}
onChange={(e) => setHour(e.target.value)}
required
/>
</div>
<div>
<label htmlFor='minute'>Select Minute</label>
<input
type='number'
min={0}
max={59}
name='minute'
id='minute'
value={minute}
onChange={(e) => setMinute(e.target.value)}
required
/>
</div>
<button>Submit</button>
</form>
</div>
);
};
export default CreateSchedule;
多个计划组件🗓📅
下面的代码片段显示了即将发生的事件。
import React from "react";
const Schedules = () => {
//create dummy schedules for now
const schedules = [
{title: "Build React project", hour: 12, minute: 0},
{title: "Dance class", hour: 14, minute: 30}]
return (
<div>
<h2>Upcoming Events</h2>
<ul>
{schedules?.map((schedule) => (
<li key={schedule.title}>
{schedule.title} - {schedule.hour} : {schedule.minute}
</li>
))}
</ul>
</div>
);
};
export default Schedules;
将应用程序连接到Socket.io服务器
在本节中,您将学习如何将事件计划保存到 Node.js 服务器,并在特定事件发生时向 React 应用程序发送通知。
将事件保存到后端服务器💾
在这里,我将指导您将计划发送并保存到后端 Node.js 服务器。
将 Socket.io 传递到文件CreateSchedule
中的组件中App.js
。
import React from "react";
import Clock from "./components/Clock";
import CreateSchedule from "./components/CreateSchedule";
import Schedules from "./components/Schedules";
import socketIO from "socket.io-client";
const socket = socketIO.connect("http://localhost:4000");
const App = () => {
return (
<div className='app__container'>
<Clock />
<CreateSchedule socket={socket} />
<Schedules />
</div>
);
};
export default App;
更新handleSubmit
函数以通过 Socket.io 将事件详细信息发送到 Node.js 服务器。
import React, { useState } from "react";
const CreateSchedule = ({ socket }) => {
const [hour, setHour] = useState(0);
const [minute, setMinute] = useState(0);
const [title, setTitle] = useState("");
const handleSubmit = (e) => {
e.preventDefault();
//sends the event details via Socket.io
socket.emit("newEvent", { hour, minute, title });
setHour("");
setMinute("");
setTitle("");
};
return <div className='createSchedule__container'>...</div>;
};
export default CreateSchedule;
在 Node.js 服务器上创建事件监听器,用于接收来自 React 应用的数据。以下代码片段将事件详情记录到终端。
socketIO.on("connection", (socket) => {
console.log(`⚡: ${socket.id} user just connected!`);
//event listener for new events
socket.on("newEvent", (event) => {
console.log(event);
});
socket.on("disconnect", () => {
socket.disconnect();
});
});
将事件保存到数组并将事件列表发送回 React 应用程序。
let eventList = [];
socketIO.on("connection", (socket) => {
console.log(`⚡: ${socket.id} user just connected!`);
/*
The event listener adds the new event
to the top of the array, and
sends the array to the React app
*/
socket.on("newEvent", (event) => {
eventList.unshift(event);
//sends the events back to the React app
socket.emit("sendSchedules", eventList);
});
socket.on("disconnect", () => {
socket.disconnect();
});
});
sendSchedules
为文件中的消息创建事件监听器App.js
。
import React, { useEffect, useState } from "react";
import Clock from "./components/Clock";
import CreateSchedule from "./components/CreateSchedule";
import Schedules from "./components/Schedules";
import socketIO from "socket.io-client";
const socket = socketIO.connect("http://localhost:4000");
const App = () => {
const [schedules, setSchedules] = useState([]);
useEffect(() => {
//listens for the event list from the backend
socket.on("sendSchedules", (schedules) => {
setSchedules(schedules);
});
}, []);
return (
<div className='app__container'>
<Clock />
<CreateSchedule socket={socket} />
<Schedules schedules={schedules} />
</div>
);
};
export default App;
上面的代码片段接受来自后端的事件列表,并将事件(时间表)数组传递到Schedules
组件中。
更新Schedules
组件如下:
import React from "react";
const Schedules = ({ schedules }) => {
return (
<div>
<h2>Upcoming Events</h2>
<ul>
{schedules?.map((schedule) => (
<li key={schedule.title}>
{schedule.title} - {schedule.hour} : {schedule.minute}
</li>
))}
</ul>
</div>
);
};
export default Schedules;
恭喜!💃🏻 我们已经能够在服务器上保存事件并在客户端显示它们了。接下来,让我们在事件发生时向用户发送通知。
使用 React Toastify 添加通知
在本节中,我将指导您在用户添加事件时以及事件发生时向 React 应用程序发送通知。
安装并配置 React Toastify如下:
//In App.js file
import React, { useEffect, useState } from "react";
import Clock from "./components/Clock";
import CreateSchedule from "./components/CreateSchedule";
import Schedules from "./components/Schedules";
import socketIO from "socket.io-client";
//React Toastify imports
import "react-toastify/dist/ReactToastify.css";
import { ToastContainer, toast } from "react-toastify";
const socket = socketIO.connect("http://localhost:4000");
const App = () => {
const [schedules, setSchedules] = useState([]);
useEffect(() => {
socket.on("sendSchedules", (schedules) => {
setSchedules(schedules);
});
}, []);
return (
<div className='app__container'>
<Clock />
<CreateSchedule socket={socket} />
<Schedules schedules={schedules} />
<ToastContainer />
</div>
);
};
export default App
更新CreateSchedule
组件以在用户添加事件计划时显示通知。
import React, { useState } from "react";
import { toast } from "react-toastify";
const CreateSchedule = ({ socket }) => {
const [hour, setHour] = useState(0);
const [minute, setMinute] = useState(0);
const [title, setTitle] = useState("");
const handleSubmit = (e) => {
e.preventDefault();
socket.emit("newSchedule", { hour, minute, title });
//👇🏻 shows toast notifications
toast.success(`${title} is successfully added!`);
setHour("");
setMinute("");
setTitle("");
};
return <div className='createSchedule__container'>...</div>;
};
export default CreateSchedule;
更新server/index.js
let eventList = [];
socketIO.on("connection", (socket) => {
console.log(`⚡: ${socket.id} user just connected!`);
socket.on("newEvent", (event) => {
eventList.unshift(event);
socket.emit("sendSchedules", eventList);
});
/*
The code snippet loops through the event list
and checks if it's time for any event
before sending a message containing
the event details to the React app
*/
let interval = setInterval(function () {
if (eventList.length > 0) {
for (let i = 0; i < eventList.length; i++) {
if (
Number(eventList[i].hour) === new Date().getHours() &&
Number(eventList[i].minute) === new Date().getMinutes() &&
new Date().getSeconds() === 0
) {
socket.emit("notification", {
title: eventList[i].title,
hour: eventList[i].hour,
mins: eventList[i].minute,
});
}
}
}
}, 1000);
socket.on("disconnect", () => {
socket.disconnect();
});
});
更新App.js
文件以在事件发生时显示通知。
import React, { useEffect, useState } from "react";
import Clock from "./components/Clock";
import CreateSchedule from "./components/CreateSchedule";
import Schedules from "./components/Schedules";
import socketIO from "socket.io-client";
import "react-toastify/dist/ReactToastify.css";
import { ToastContainer } from "react-toastify";
import { toast } from "react-toastify";
const socket = socketIO.connect("http://localhost:4000");
const App = () => {
const [schedules, setSchedules] = useState([]);
useEffect(() => {
socket.on("sendSchedules", (schedules) => {
setSchedules(schedules);
});
//Listens for the notification from the server
socket.on("notification", (data) => {
toast.success(` It's time for ${data.title}`);
});
}, []);
return (
<div className='app__container'>
<Clock />
<CreateSchedule socket={socket} />
<Schedules schedules={schedules} />
<ToastContainer />
</div>
);
};
export default App;
您已完成基本事件安排,并在浏览器上显示它💁🏻♀️
额外:向用户发送推送通知🙋🏻♂️
如果网页打不开怎么办?如何确保用户不会错过行程,并且即使不在网页上也能收到通知?
推送通知是最好的解决方案。
即使 Web 应用程序未打开,推送通知也会出现在您的桌面或主屏幕上。在这里,我将指导您如何使用 Firebase 和 Novu 发送推送通知。
设置 Firebase 云消息传递
转到 Firebase 控制台,登录并创建一个 Firebase 项目。
点击图标,在项目中创建一个 Firebase Web 应用</>
。
创建一个src/firebase.js
文件,并将 Firebase JavaScript SDK 配置复制到该文件中
//👉🏻 In client/src/firebase.js
import { initializeApp } from "firebase/app";
const firebaseConfig = {
apiKey: "...",
authDomain: "...",
projectId: "...",
storageBucket: "...",
messagingSenderId: "...",
appId: "...",
};
// Initialize Firebase
const app = initializeApp(firebaseConfig);
将 Firebase 安装到您的 React 项目。
cd client
npm install firebase
点击 Firebase 应用信息中心侧边栏上“项目概览”旁边的“设置”图标,然后选择“项目设置”。
导航到“云消息传递”选项卡并生成 Web Push 证书密钥对。
更新firebase.js
文件以包含以下代码并添加 Web Push 证书作为vapidKey
变量。
import { initializeApp } from "firebase/app";
import { getMessaging, getToken, onMessage } from "firebase/messaging";
const firebaseConfig = {
apiKey: "...",
authDomain: "...",
projectId: "...",
storageBucket: "...",
messagingSenderId: "...",
appId: "...",
measurementId: "...",
};
// Initialize Firebase
const firebaseApp = initializeApp(firebaseConfig);
//Access Firebase cloud messaging
const messaging = getMessaging(firebaseApp);
/*
This function allows us to get your device token from Firebase
which is required for sending Push notifications to your device.
*/
export const getTokenFromFirebase = () => {
return getToken(messaging, {
vapidKey: "<YOUR_WEB_PUSH_CERTIFICATE>",
})
.then((currentToken) => {
if (currentToken) {
console.log("current token for client: ", currentToken);
} else {
console.log(
"No registration token available. Request permission to generate one."
);
}
})
.catch((err) => {
console.log("An error occurred while retrieving token. ", err);
});
};
//This function listens to push messages on the server
export const onMessageListener = () =>
new Promise((resolve) => {
onMessage(messaging, (payload) => {
console.log(payload);
resolve(payload);
});
});
在 React 应用程序的公共文件夹中创建一个服务工作文件。
cd client/public
touch firebase-messaging-sw.js
将下面的代码片段复制到firebase-messaging-sw.js
文件中。
// Scripts for firebase and firebase messaging
importScripts(
"https://www.gstatic.com/firebasejs/9.0.0/firebase-app-compat.js"
);
importScripts(
"https://www.gstatic.com/firebasejs/9.0.0/firebase-messaging-compat.js"
);
const firebaseConfig = {
apiKey: "...",
authDomain: "...",
projectId: "...",
storageBucket: "...",
messagingSenderId: "...",
appId: "...",
measurementId: "...",
};
firebase.initializeApp(firebaseConfig);
// Retrieve firebase messaging
const messaging = firebase.messaging();
messaging.onBackgroundMessage(function (payload) {
console.log("Received background message ", payload);
const notificationTitle = payload.notification.title;
const notificationOptions = {
body: payload.notification.body,
};
self.registration.showNotification(notificationTitle, notificationOptions);
});
导航到App.js
文件并调用文件中的函数firebase.js
。
//....other imports
//👉🏻 Import the functions from the Firebase.js file
import { getTokenFromFirebase, onMessageListener } from "./firebase";
const socket = socketIO.connect("http://localhost:4000");
const App = () => {
const [schedules, setSchedules] = useState([]);
useEffect(() => {
//👉🏻Logs the device token to the console
getTokenFromFirebase();
//👉🏻Listen and logs the push messages from the server.
onMessageListener()
.then((payload) => {
console.log("From Message", payload);
})
.catch((err) => console.log("failed: ", err));
//....socket.io listeners
}, []);
return (
...
);
};
export default App;
运行 React 应用服务器;你的设备令牌将会显示在控制台中。复制并保存该令牌,以便在后续部分使用。
导出 Firebase
返回 Firebase 应用信息中心。在“项目设置”下,导航到“服务帐户”选项卡,然后点击Generate a new private key
按钮下载您的服务帐户凭据(JSON 文件类型)。
Novu——开源库
一旦有新的通知,我们可以使用 Novu 向用户发送推送通知,您也可以使用其他服务(例如OneSignal)或者您可以自己实现。
导航到客户端文件夹并通过运行以下代码创建一个 Novu 项目。
cd client
npx novu init
在创建 Novu 项目之前,您需要使用 Github 登录。以下代码片段包含运行后应遵循的步骤 npx novu init
Now let's setup your account and send your first notification
❓ What is your application name? Devto Clone
❓ Now lets setup your environment. How would you like to proceed?
> Create a free cloud account (Recommended)
❓ Create your account with:
> Sign-in with GitHub
❓ I accept the Terms and Condidtions (https://novu.co/terms) and have read the Privacy Policy (https://novu.co/privacy)
> Yes
✔️ Create your account successfully.
We've created a demo web page for you to see novu notifications in action.
Visit: http://localhost:57807/demo to continue
访问演示网页 http://localhost:57807/demo
,复制您的订阅者 ID,然后点击“跳过教程”按钮。我们将在本教程的后续部分使用它。
在仪表板上的集成商店部分下选择推送,将已下载的服务帐户凭据的内容复制到输入字段中并保存。
从侧边栏中选择通知,并为推送消息创建通知模板。
通过将 Push 添加到其工作流程来编辑模板
选择推送步骤,添加推送通知内容,保存。
接下来,在服务器上安装并配置 Novu。
/*
👉🏻 Run npm install @novu/node in your terminal
*/
const { Novu, PushProviderIdEnum } = require("@novu/node");
const novu = new Novu("<YOUR_API_KEY>");
通过文件中的 Novu 发送推送通知请求server/index.js
,更新/api
路由如下:
app.get("/api", async (req, res) => {
const subscriberId = "<YOUR_NOVU_SUBSCRIBER_ID>";
await novu.subscribers.identify(subscriberId, {
firstName: "<YOUR_FIRST_NAME>",
lastName: "<YOUR_LAST_NAME>",
});
await novu.subscribers.setCredentials(subscriberId, PushProviderIdEnum.FCM, {
deviceTokens: ["<YOUR_DEVICE_TOKEN_FROM_REACT_APP_CONSOLE>"],
});
const trigger = await novu.trigger("<NOTIFICATION_TEMPLATE_ID>", {
to: {
subscriberId,
},
});
res.json(trigger.data);
});
恭喜!我们已经可以通过 Novu 发送推送通知了。
注意:当您检查 React 应用程序 JavaScript 控制台时,它还会记录推送通知内容。
要在事件发生时发送通知,请创建一个函数,在事件发生时通过 Novu 发送推送通知,如下所示:
async function sendNotification(message) {
const subscriberId = "<YOUR_NOVU_SUBSCRIBER_ID>";
await novu.subscribers.identify(subscriberId, {
firstName: "<YOUR_FIRST_NAME>",
lastName: "<YOUR_LAST_NAME>",
});
await novu.subscribers.setCredentials(subscriberId, PushProviderIdEnum.FCM, {
deviceTokens: ["<YOUR_DEVICE_TOKEN_FROM_REACT_APP_CONSOLE>"],
});
const trigger = await novu.trigger("<NOTIFICATION_TEMPLATE_ID>", {
to: {
subscriberId,
},
/*👇🏻 payload allows you to pass data into the notification template
Read more here: https://docs.novu.co/platform/templates/#variable-usage
*/
payload: {
message,
},
});
}
socketIO.on("connection", (socket) => {
console.log(`⚡: ${socket.id} user just connected!`);
socket.on("newSchedule", (schedule) => {
eventList.unshift(schedule);
socket.emit("sendSchedules", eventList);
});
let interval = setInterval(function () {
if (eventList.length > 0) {
for (let i = 0; i < eventList.length; i++) {
if (
Number(eventList[i].hour) === new Date().getHours() &&
Number(eventList[i].minute) === new Date().getMinutes() &&
new Date().getSeconds() === 0
) {
sendNotification(eventList[i].title);
}
}
}
}, 1000);
socket.on("disconnect", () => {
socket.disconnect();
});
});
结论
到目前为止,您已经学习了如何向 React 应用程序添加数字时钟、在 React 应用程序和 Socket.io 服务器之间间隔发送消息和通知以及如何使用 Novu 和 Firebase 向用户发送推送通知。
您还可以使用 Novu 和 Firebase 改进此应用程序并向各种应用程序添加推送通知。
本教程的源代码可以在这里找到:https://github.com/novuhq/blog/tree/main/event-scheduler-with-push-notifications
感谢您的阅读!
文章来源:https://dev.to/novu/building-a-live-event-alert-system-with-react-socketio-and-push-notifications-2jg5