My problem
I render a list of simple items (numbers or strings) using Array.map
method. I use Modal
to add/update items. However, every opening or closing of the modal makes react
rerender the whole array, even if the array remains unmodified. I feel this is an expected behavior.
Questions
- Is it possible not to rerender the whole component when opening or closing the modal?
- What is the common way to add/update new items in array without rerendering the entire list?
Thanks, guys
Minimal code example
/* Console output:
* ---------------
* ROOT: render component
* -> ITEM: render 1
* -> ITEM: render 2
* -> ITEM: render 3 (not in map)
* ROOT: open modal
* ROOT: render component
* -> ITEM: render 1
* -> ITEM: render 2
* -> ITEM: render 3 (not in map)
* MODAL: close Modal
* ROOT: render component
* -> ITEM: render 1
* -> ITEM: render 2
* -> ITEM: render 3 (not in map)
*/
import * as React from 'react';
import {useState} from 'react';
import {View, Text, Modal, Pressable, StyleSheet} from 'react-native';
const items = [1, 2];
const Item = ({el}) => {
console.log(`-> ITEM: render ${el}`);
return <Text>Item: {el}</Text>;
};
const Testing = () => {
const [visible, setVisible] = useState(false);
const openModal = () => {
console.log('ROOT: open modal');
setVisible(true);
};
console.log("ROOT: render component");
return (
<View style={styles.wrapper}>
{/* Render simple list */}
<Text style={styles.header}>All items:</Text>
{items.map(el => (
<Item el={el} key={el} />
))}
<Item el={'3 (not in map)'} />
{/* Button to open modal */}
<Pressable style={styles.button} onPress={openModal}>
<Text style={styles.header}>Tap me to open modal</Text>
</Pressable>
{/*The Modal*/}
<Modal
animationType="slide"
transparent={false}
visible={visible}
onRequestClose={() => {
console.log('MODAL: close Modal');
setVisible(false);
}}>
<Text style={styles.header}>No content here...</Text>
</Modal>
</View>
);
};
const styles = StyleSheet.create({
wrapper: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
},
button: {
borderRadius: 5,
backgroundColor: '#0aa',
marginVertical: 10,
padding: 10,
},
header: {
fontSize: 18,
fontWeight: '700',
},
});
export default Testing;