React Native - How to prevent unwanted unmounting of components? - react-native

I have a sort of WhatsApp clone project. From the users listing component, it will redirect to each users chatWindow. I dont want to re-render the chatWindow component which was already rendered.
This is what happening
Navigate to ChatWindow1 from Userchannel - ChatWindow1 mounted
Navigate to Userchannel from ChatWindow1 - ChatWindow1 unmounted
Navigate to ChatWindow2 from Userchannel - ChatWindow2 mounted
Navigate to Userchannel from ChatWindow2 - ChatWindow2 unmounted
Navigate to ChatWindow1 from Userchannel - ChatWindow1 mounted again.
I know using state we can render the ChatWindow again. But Is there a possibility to avoid the unwanted re-renderng. Currently I am usinf RNRF as the router.

Optimising re-render can be done in multiple ways in react.
You can use PureComponent Implementation where react itself shallow compares the props and re-renders only when necessary.
If you want more granular control, go with shouldComponentUpdate which gives you a lifecycle method where you can compare the props and decide whether you want to avoid render. Please make sure the comparison is not complex. The more complex comparisons can make the app slow, in which case the optimisation back fires.
Use Flat list instead of List view or scrollview for better performance and make sure you add a keyExtractor and Item as a PureComponent.
Make sure the code splitting is properly done. you cannot optimise a very large amount code in a single page. If the components are small enough, you can optimise them better.
If you have a lot going on the JS, I would strongly recommend using a native navigation solution like react-native navigation
You can use console logs in render to find out the render count and take necessary actions. Please make sure that these optimisations can block necessary renders as well. So make sure props are different when you want to re-render things.
Regarding the mount / unmount
In most cases the navigation keeps the screens in the stack. Going back will not trigger a re-render. You can do one thing, make sure page works on props, so that re-render happens only when data changes.
Helpful Links:
https://medium.com/#ohansemmanuel/how-to-eliminate-react-performance-issues-a16a250c0f27
https://medium.com/vena-engineering/optimizing-react-rendering-61a10e741edb

Since your screens are unmounted there is nothing wrong to re-render when you navigate back to that screen. Of course you could avoid this by having all your screens mounted but that might cause memory leak.

Related

Is there a way to overlay react-navigation headers from within a screen?

Wondering if there's a simple way to overlay react-navigation's Stack and MaterialTopTabNavigator components within individual screens. I need to overlay both when displaying components such as loading overlays and dialog/prompt components.
I understand I could define these components within the same root file as the navigation, however this means I have to track the state of the dialog within redux or some other shared state, which I would prefer to avoid in an effort to be more declarative/functional.
Can't find any good solutions, and I'm combing through react-navigation's source code, but if someone else has already solved this it would save me a lot of time. Thanks!
Edit: I also don't want to use react-native's modal or react-native-modal. Would like to implement a custom component myself.

Can pure component use redux actions?

I have a FlatList which I would like to optimize by using pure components.
As I am new to react-Native I am not sure how pure component will act in a situation were actions(functions) will be passed as props.
I know that their benefit is reached by shalow comparison of state and props which prevents rerender but I am not sure how a redz action will affect.
I assume that since it doesn't change it won't affect the performance.
Is this assumption is correct?
FlatList is already a PureComponent and I would definitely not suggest to optimize it in this way as you can easily run into bugs. It already takes care of rerendering things when necessary. But answering your question - same redux action is the same function across rerenders, you can comfirm it with console.log(this.props.myAction === this.props.myAction)

Updating inactive screens conditionally react-native

I have this react-native application using AppNavigator handling navigation between screens. I have trouble updating the paused (AppNavigator calls these screens "Blurred") screens.
I would like to be able to update the inactive screens from an active one.
I tried to add a listener on app notifications or subscribing to specific changes in a mobx store that should update the component, however the screen component won't react when not active/focused.
How can I make sure the screens updates when not active? I am unsure if I am tackling this fundamentally wrong.
In previous versions of react-navigation there was a way to disable lazy loading but that has been taken out in the newer versions.
What you are asking for will hinder you in the long term. It will basically keep all the screens loaded in the memory. You shouldn't need that just to update them. Instead you can update the MobX store and when the screen becomes active again look for the changes and update accordingly.
Use NavigationEvents to listen to when the screen becomes active.

Lifecycle functions involved in StackNavigation

Currently, I read some state from AsyncStorage in componentWillMount. However, some screens modify what is in AsyncStorage, and it does not appear that componentWillMount is called when returning (this.props.navigation.goBack()) to a screen, so they don't receive the update.
What, if anything, is called? What are the component lifecyle functions that are called on the return to a screen? Are any of these only called once, when the screen is to be shown again?
componentDidFocus is currently in design not avaiable yet, see react-native open issue #51.
Try this alternative way react-navigation-addons.

Optimizing performance react-native component containing an image

I have a component in my app that uses an image as a background. The component is a chat screen where users can view previous messages and send new ones. The component is connected to redux store. The component looks like this at a high level
// Chat screen
<Image>
<Messages />
<TextInput />
</Image>
The chat screen component will be re-rendered every time user types anything. Sometimes, users have reported a lag in typing and seeing the typed character on screen. I am thinking if it is due to the fact that Image is also re-rendered every time user types something and if it would make sense to extract the Messages and TextInput into a separate component and connect that to the redux store such that the Image is not re-rendered when user is typing.
I don't want to make this change if it is not going to affect the performance and I don't have a sure shot way to measuring if that change has affected the performance as the lag is very intermittent.
Let me know if you think this would affect the performance of the component.
Using an image as a background can make performance issue, especially on Android. Use minified images as a background. Also, Try to capsulate the state change to the TextInput component by making a wrapper for it. It's a good idea to use FlatList for Messages component too.