Reputation: 65
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.
Upvotes: 3
Views: 5364
Reputation: 4992
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,
},
});
Upvotes: 4