» Make Web Chat App Front-End with React » 2. Development » 2.8 Add Sounds

Add Sounds

We use howler to play sounds.

npm i howler

Changes in 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);
  • We use Howl to play the "ding" sound effect.
  • Most importantly, we use setPickedContact and setIsGroupChatting state methods to "hack" the values and use them to calculate the results of contactNotifications and groupNotifications.
  • With this hack, we don't need to manually avoid the red dots for the current conversation.

Open 4 browser windows and try to private chat or group chat with each other. You'll see the red dots and hear the "ding" sounds.

PrevNext