I’m attempting to build an app that acts as a soundboard and can play different sounds when different buttons are pressed. I expected the audio to play but instead, I got an error that stated:
Possible Unhandled Promise Rejection (id: 1): TypeError: undefined is not an object (evaluating '_expoAv.Audio.sound.createAsync') playSound$
This is my code:
import { StatusBar } from "expo-status-bar"; import React, { useState, useEffect } from "react"; import { StyleSheet, Text, View, TouchableOpacity } from "react-native"; import { Feather } from "@expo/vector-icons"; import { Audio } from "expo-av"; // project made in yarn // yarn start // yarn add export default function App() { const [sound, setSound] = useState(""); const playSound = async () => { console.log("Loading Sound"); const { sound } = await Audio.sound.createAsync( require("./assets/Ayo.mp3") ); setSound(sound); console.log("playing sound"); await sound.playAsync(); }; useEffect(() => { return sound ? () => { console.log("unloading the sound"); sound.unloadAsync(); } : undefined; }, [sound]); // run useEffect whenever sound state changes return ( <View style={styles.container}> <Text>SoundGround</Text> <View style={{ flexDirection: "row" }}> <TouchableOpacity onPress={playSound}> <Feather name="arrow-left" style={styles.iconStyle} /> </TouchableOpacity> <TouchableOpacity onPress={playSound}> <Feather name="arrow-right" style={styles.iconStyle} /> </TouchableOpacity> </View> <StatusBar style="auto" /> </View> ); } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: "#fff", alignItems: "center", justifyContent: "center", }, iconStyle: { fontSize: 100, }, });
So far, I’ve tried adding a try/catch block, using different audio formats. I think the error has to do with state not being assigned before it is used to play something – but I’m not sure.
Advertisement
Answer
You can implement useRef
instead of useState
to stop re-rendering!
This worked for me very well.
import { StatusBar } from "expo-status-bar"; import React, { useEffect } from "react"; import { StyleSheet, Text, View, TouchableOpacity } from "react-native"; import { Feather } from "@expo/vector-icons"; import { Audio } from "expo-av"; // project made in yarn // yarn start // yarn add export default function App() { const sound = useRef(new Audio.Sound()); useEffect(() => { return () => sound.current.unloadAsync(); }, []); const playSound = async () => { console.log("Loading Sound"); await sound.current.createAsync(require("./assets/Ayo.mp3")); console.log("playing sound"); const checkLoaded = await sound.current.getStatusAsync(); if (checkLoaded.isLoaded === true) { console.log("Error in Loading mp3"); } else { await sound.current.playAsync(); } }; return ( <View style={styles.container}> <Text>SoundGround</Text> <View style={{ flexDirection: "row" }}> <TouchableOpacity onPress={() => playSound()}> <Feather name="arrow-left" style={styles.iconStyle} /> </TouchableOpacity> <TouchableOpacity onPress={() => playSound()}> <Feather name="arrow-right" style={styles.iconStyle} /> </TouchableOpacity> </View> <StatusBar style="auto" /> </View> ); } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: "#fff", alignItems: "center", justifyContent: "center", }, iconStyle: { fontSize: 100, }, });