I have a particular case in my RN application.
I have a Webview to load a third-party widget on a particular Screen.
The flow is something similar to:
- Main screen contains a list of items
- Each item is clickable and opens an ItemDetails screen
- Within this ItemDetails screen I use the Webview widget that uses as an argument a value from the displayed Item
The issue is that every time I navigate to an ItemDetails screen the Webview needs to be initialised, HTML/JS/CSS content downloaded and executed. When going back to main screen, the Webview gets unmounted and destroyed When opening a different item, all the Webview initialisation starts again.
The trick is that I can just change the URL to load the information for the new Item, without the requirement of fully reloading the Webview.
Is there any option to keep the WebView open, so between navigations I can avoid all the mounting delay and the information can be presented a lot faster.
technical details:
- The app is using expo managed flow
- We use react-navigation to navigate between screens
The following codes are just a simplification as an example of the current project.
- Stack declaration is:
import { createStackNavigator } from '@react-navigation/stack';
const Stack = createStackNavigator();
function MyStack() {
return (
<Stack.Navigator>
<Stack.Screen name="ItemsList" component={ItemList} />
<Stack.Screen name="ItemDetails" component={ItemDetails} />
</Stack.Navigator>
);
}
- Itemlist:
import React from 'react';
import { SafeAreaView, TouchableOpacity, FlatList, StyleSheet, Text, StatusBar } from 'react-native';
const DATA = [
{
id: 'bd7acbea-c1b1-46c2-aed5-3ad53abb28ba',
title: 'First Item',
},
{
id: '3ac68afc-c605-48d3-a4f8-fbd91aa97f63',
title: 'Second Item',
},
{
id: '58694a0f-3da1-471f-bd96-145571e29d72',
title: 'Third Item',
},
];
const Item = ({ title, id }) => (
<TouchableOpacity style={styles.item} onPress={() => navigation.navigate('ItemDetails', { id })}>
<Text style={styles.title}>{title}</Text>
</View>
);
const App = () => {
const renderItem = ({ item }) => (
<Item title={item.title} />
);
return (
<SafeAreaView style={styles.container}>
<FlatList
data={DATA}
renderItem={renderItem}
keyExtractor={item => item.id}
/>
</SafeAreaView>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
marginTop: StatusBar.currentHeight || 0,
},
item: {
backgroundColor: '#f9c2ff',
padding: 20,
marginVertical: 8,
marginHorizontal: 16,
},
title: {
fontSize: 32,
},
});
export default App;
- ItemDetails:
import React, { Component } from 'react';
import { WebView } from 'react-native-webview';
const ItemDetails = ({ route }) => (
<WebView
source={{ uri: `https://thirdpartywidget.com/${route.params.id}` }}
style={{ marginTop: 20 }}
/>
)