I'm trying to make a metronome using react native, but I'm having trouble with the sound playback. I've used ExpoAV to play sound, but when I run it on the expo app it's very choppy and sometimes plays offbeat. I'm guessing the best way to play sounds on time is to use native modules? Is there a way to fix it right in react native?
Here's the code I use:
const soundTimer = setInterval(() => {
if (clickSound._loaded) {
try {
clickSound.replayAsync();
} catch (err) {
console.log(err.message);
}
}
}, 60000/tempo);
Edit:
After some more intensive searching, I found an already answered question on here on Stack Overflow (I know, could've done that before...). Basically, the problem wasn't with the expo-av module, but with the JavaScript timer which is made to balance precision and performance on a single thread. Here is the link.
I created the demo: https://snack.expo.io/SJSNohTYS
Changed the workflow of the code with useEffect and async await.
Related
According to expos documentation, if I want user to navigate to another screen after user taps the notification received I should use deep linkedin. thats also the suggested method in all similar posts Ive seen. In my case I just do the following:
useEffect(()=> {
responseListener.current = Notifications.addNotificationResponseReceivedListener(response => {
if (response) {
navigation.navigate("Page 1")
}
});
}, [])
It works fine, when I have app open or closed. I wonder if I just dont understand something and there will be issues as everywhere I read deep linking. Thanks!
I am trying to implement deep linking/universal linking with my React Native app and it works good so far, but one thing. I have an eventListener and getInitialUrl in my app.js like so:
useEffect(() => {
Linking.addEventListener("url", (url) => handleInvite(url));
Linking.getInitialURL().then((url) => handleInvite(url));
}, []);
getInitialUrl works fine and the app opens and gets the url. This function is when the app is not active in the background. However, when the app is in the background the eventListener gets fired and the app crashes immediately. I tested it with and without and the problem is the eventListener, but I don't know why.
The app crashes immediately and I can't find any info on this problem. So any help would be much appreciated.
This is tested on iOS.
So I found the problem. Basically the addEventListener returns an array and not a string. So when using that in the function it caused the app to crash.
The right way to add the eventListener is like this:
Linking.addEventListener("url", event => handleInvite(event.url));
It is weird that no where in the docs this example is given. But it works now atleast!
componentDidMount() {
Linking.addEventListener('url', event =>
this.handleOpenURL(event.url));
Linking.getInitialURL().then(url => {
console.log('url===',url);
if(url)
this.handleOpenURL(url);
});
}
handleOpenUrl is never called if the app is already open and I try to change the deep link Url. If the app is already not open then it opens the app and gets the URL.
Actually it was the issue with FBSDK overriding the method.
This solution worked for me.
https://github.com/react-navigation/react-navigation/issues/798#issuecomment-290363058
I was having this issue working on a detached Expo project because I had added the suggested code from https://facebook.github.io/react-native/docs/linking.html to the *AppDelegate.m but Expo already provides slightly different functions for handling URL events. Removing the code from the React Native docs made it work for me.
I am using redux-persist in a react native project, that runs just fine in a broad number of devices except Android 7. I am trying to debug the problem on why my local storage is nor persisting and found this:
The following code executes inside React Native component lifecycle's
componentDidMount() {
attachObservables(store)
setInterval(async () => {
console.log('Inside setInterval')
const data = await AsyncStorage.getAllKeys()
console.log('inside the getAllKeys')
data.forEach(async k => {
const value = await AsyncStorage.getItem(k)
console.group(k)
console.log(value)
console.groupEnd()
})
}, 3000)
}
Code after 'Inside setInterval' is never called. It only runs once if outside the setInterval. If I call once the code outside the setInterval it appears to run just fine. I also tried callback format vs async / await version but it does not seem to matter.
Same problem I had using firebase js library (callbacks never return after the first one). I am now looking for alternatives to workaround the problem.
Any ideas?
As of React Native 0.51 in some Android versions, the runtime can get blocked by other native modules, impeding the resolution of the mentioned methods.
It can be fixed via https://github.com/facebook/react-native/issues/14101#issuecomment-345563563, ensuring this methods use a free thread from the thread pool.
A PR has been submitted and I hope that will be released in future versions. If you want it to use this fix right now, it is available here https://github.com/netbeast/react-native
EDIT:
I am not experiencing this anymore on real devices over react-native#0.53, anyhow others have also reported, so the issue is still open.
I'm using the Lottie imperative API to display a looping animation.
The imperative API works fine on all of my components except one that uses React Native Sound. I assume the problem is that both libraries are called with .play(). Is this possible?
Lottie: this.animation.play();
React Native Sound: this.sound.play()
After calling the Lottie method, I'm getting the Error Message:
Cannot read property 'play' of undefined
Any Ideas?
Thanks in advance.
I eventually figured it out. React Native Sound of course wasn't the problem - it might have just delayed the initialization of Lottie and thus animation was still undefined when I called it.
The solution is to build in a timer and was already suggested in this thread: https://github.com/airbnb/lottie-react-native/issues/21
componentDidMount() {
this.initAnimation();
}
initAnimation(){
if (!this.animation){
setTimeout(() => {
this.initAnimation();
}, 100);
} else {
this.animation.play();
}
}