» React创建在线聊天软件 Web Chat App 前端 » 2. 开发 » 2.8 添加音效

添加音效

我们使用 howler 来播放音效。

npm i howler

变更 src/App.js:

@@ -8,6 +8,7 @@ import CreateGroup from "./components/create-group";
 import Group from "./components/group";
 import clsx from "clsx";
 import io from "socket.io-client";
+import { Howl } from "howler";
 
 function randomString(length) {
   const characters =
@@ -20,6 +21,18 @@ function randomString(length) {
   return result;
 }
 
+// Sounds from https://pixabay.com/sound-effects/search/ding/
+const SOUNDS = {
+  ding: process.env.PUBLIC_URL + "/ding.mp3",
+};
+
+function dingIt() {
+  const sound = new Howl({
+    src: [SOUNDS.ding],
+  });
+  sound.play();
+}
+
 function App() {
   const [logged, setLogged] = useState(false);
   const [creatingGroup, setCreatingGroup] = useState(false);
@@ -55,8 +68,18 @@ function App() {
         const newMessages = [...oldMessages, entry];
         return { ...cm, [from]: newMessages };
       });
-      setContactNotifications((cn) => {
-        return { ...cn, [from]: true };
+      // Hack to get `pickedContact` and `isGroupChatting` state value
+      setPickedContact((pc) => {
+        setIsGroupChatting((igc) => {
+          if (!pc || igc || pc.sid !== from) {
+            dingIt();
+            setContactNotifications((cn) => {
+              return { ...cn, [from]: true };
+            });
+          }
+          return igc;
+        });
+        return pc;
       });
     });
     socket.on("create-group", (data) => {
@@ -74,8 +97,18 @@ function App() {
         const newMessages = [...oldMessages, entry];
         return { ...gm, [roomId]: newMessages };
       });
-      setGroupNotifications((gn) => {
-        return { ...gn, [roomId]: true };
+      // Hack to get `pickedContact` and `isGroupChatting` state value
+      setPickedContact((pc) => {
+        setIsGroupChatting((igc) => {
+          if (!pc || !igc || pc.id !== roomId) {
+            dingIt();
+            setGroupNotifications((gn) => {
+              return { ...gn, [roomId]: true };
+            });
+          }
+          return igc;
+        });
+        return pc;
       });
     });
     socket.emit("user-join", user);
@@ -92,20 +125,6 @@ function App() {
       resultEndRef.current?.scrollIntoView({ behavior: "smooth" });
   }, [contactMessages, groupMessages, pickedContact]);
 
-  useEffect(() => {
-    // Avoid red dots for the current conversation
-    if (!pickedContact) return;
-    if (isGroupChatting) {
-      setGroupNotifications((gn) => {
-        return { ...gn, [pickedContact.id]: false };
-      });
-    } else {
-      setContactNotifications((cn) => {
-        return { ...cn, [pickedContact.sid]: false };
-      });
-    }
-  }, [contactMessages, groupMessages, pickedContact, isGroupChatting]);
-
   const login = (emoji, name) => {
     setUser({ emoji, name });
     setLogged(true);
  • 使用 Howl 来播放“叮”的音效。
  • 更重要地是,我们使用 setPickedContactsetIsGroupChatting state 方法来“hack”到它们的状态值并用于计算contactNotificationsgroupNotifications 的结果。
  • 有了这个“hack”之后,我们不再需要担心当前对话框误产生的红点。

打开 4 个浏览器窗口然后尝试单聊、群聊功能。你将看到很多小红点,听到许多“叮”声。