How to catch component unmount caused by live reload - react-native

[edit - I thought I was using Hot Reloading, but I am actually using Live Reload]
I have a native plugin that needs to do some clean up each time it is finished with. Basically I want to prevent these errors:
Calling JS function after bridge has been destroyed: RCTDeviceEventEmitter.emit(..)
componentWillUnmount() doesn't get called.

Live reloading will restart the app and load the app back to the initial route when a file changes. ComponentWillUnmount won't be called.
When you reload, what happens behind the scenes is that the react context is getting destroyed, and a new one is being created.
That error get's thrown whenever a Native Module is trying to do work, by using the old react context.

You could use something like this:
Error Boundary in react
Just wrap the error prone code inside the ErrorBoundary component, e.g.
<ErrorBoundary><childComponentCausingError></ErrorBoundary>
And in the ErrorBoundary component, you could just catch the error in componentDidCatch = (error, info) => {
}
componentDidCatch() is a lifecycle method in React.

Related

Nuxt js application freezing without any reason

I have Navigation component in my nuxt application and it use window object and I know it has problem with SSR.
I have imported this component in default layout. But I commented this component in default.vue layout, but still gives error and freezing!
error message:
window is not defined
I'm confused.
Try it with this:
if (process.client) {
// put your code that should be executed on the client side here
}

React-native lifecycle methods warning: " componentWillReceiveProps is deprecated and will be removed in the next major version"

While using the life-cycle methods in react-native, I have encountered the following warning messages in the console as well as in the emulator:
Warning: componentWillReceiveProps is deprecated and will be removed in the next major version. Use static getDerivedStateFromProps instead.
Warning: componentWillMount is deprecated and will be removed in the next major version. Use componentDidMount instead. As a temporary workaround, you can rename to UNSAFE_componentWillMount.
The warnings are even displayed annoyingly in the emulator as follows:
The problem arises whenever i dismiss the warning messages in the emulator, the application crashes, hence i have to restart the application again.
What can I do about this?
Also, despite the warning messages, I have never used the method "componentWillReceiveProps". However, I have made use of the method "componentWillMount". What could be the cause of receiving warning message even related to method "componentWillReceiveProps"?
I think it does not affect your application, it's just annoying.
Hide it by add below into index.js:
import { YellowBox } from 'react-native';
YellowBox.ignoreWarnings([
'Warning: componentWillMount is deprecated',
'Warning: componentWillReceiveProps is deprecated',
'Module RCTImageLoader requires',
]);
These deprecation notices was not due to land in React Native 0.54 but was by mistake, you can upgrade React Native to 0.54.1 and see that these messages are gone.
Read more here.
Just replace
componentWillReceiveProps(nextProps) { ... }
with
static getDerivedStateFromProps(nextProps, prevState) { ... }
and use prevState as your current state.
remember, this method should return an object to update the state or null to update nothing and doesn't have access to the component instance. something like redux.
see this

componentWillMount is deprecated and will be removed in the next major version 0.54.0 in React Native

I use the react native latest version of 0.54.0 and Whenever run the apps on iOS there is found warning about deprecate the lifecycle methods. and also please update the components.
Warning :
componentWillMount is deprecated and will be removed in the next major version. Use componentDidMount instead. As a temporary workaround, you can rename to UNSAFE_componentWillMount.
Please update the following components: Container, Text, TouchableOpacity, Transitioner, View
I Have also change according to the waring add prefix UNSAFE_ each of the method.
UNSAFE_componentDidMount() {
}
UNSAFE_componentWillMount() {
}
UNSAFE_componentWillUpdate(nextProps, nextState) {
}
UNSAFE_componentWillReceiveProps(nextProps) {
}
Although the warning continue. Please help me.
Currently I have hide the YellowBox waring in my Apps.
import { YellowBox } from 'react-native';
render() {
YellowBox.ignoreWarnings([
'Warning: componentWillMount is deprecated',
'Warning: componentWillReceiveProps is deprecated',
]);
}
You should move all the code from the componentWillMount to the constructor or componentDidMount.
componentWillMount() is invoked just before mounting occurs. It is called before render(), therefore calling setState() synchronously in this method will not trigger an extra rendering. Generally, we recommend using the constructor() instead.
Avoid introducing any side-effects or subscriptions in this method. For those use cases, use componentDidMount() instead.
This is the only lifecycle hook called on server rendering.
componentDidMount() is invoked immediately after a component is mounted. Initialization that requires DOM nodes should go here. If you need to load data from a remote endpoint, this is a good place to instantiate the network request.
This method is a good place to set up any subscriptions. If you do that, don’t forget to unsubscribe in componentWillUnmount().
Calling setState() in this method will trigger an extra rendering, but it will happen before the browser updates the screen. This guarantees that even though the render() will be called twice in this case, the user won’t see the intermediate state. Use this pattern with caution because it often causes performance issues. It can, however, be necessary for cases like modals and tooltips when you need to measure a DOM node before rendering something that depends on its size or position.
From the official docs
componentDidMount isn't deprecated and is definitely still safe to use, so there's no need to add UNSAFE_ to that method. The componentWillSomething methods are the ones that seem to be on their way out. Instead of componentWillMount, use a constructor for the stuff that doesn't produce side-effects, and use componentDidMount for the stuff that does.
You should avoid using componentWillSomething in order to use constructor or componentDidMount
However, You have to be very carefully which one you'll use. A typical scenario is when you want to display a loading (using states) immediately after you open a screen
this.setState({ isLoading: true });
...
this.setState({ isLoading: false});
In this kind of case you have to use componentDidMount in order to set states. This is what React said about constructors
Typically, in React constructors are only used for two purposes:
Initializing local state by assigning an object to this.state.
Binding event handler methods to an instance.
You should not call setState() in the constructor(). Instead, if your component needs to use localstate, assign the initial state to this.state directly in the constructor.
Good coding!

AsyncStorage is not returning the callback

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.

How to handle back button after returning a promise from the activate callback in Durandal

We are developing a mobile application using Durandal 2.1
The documentation states that we can return a promise from the activate callback and it should cancel navigation on failure.
We've been trying to use that feature, but it breaks the back button in our application.
As you can see in Durandal's router.js plugin code, the cancelNavigation function is navigating towards the lastUrl:
function cancelNavigation(instance, instruction) {
system.log('Navigation Cancelled');
router.activeInstruction(currentInstruction);
router.navigate(lastUrl, false);
isProcessing(false);
rootRouter.explicitNavigation = false;
rootRouter.navigatingBack = false;
router.trigger('router:navigation:cancelled', instance, instruction, router);
}
Because of that behavior, using the back button after navigation cancellation will not provide the expected results since it will navigate back to the page that caused the error.
Are we using this feature in the wrong way?
Our goal is to try to load data in the activate function, and then navigate back to the current page if an error occurs.
Any help regarding this woule be greatly appreciated.