What I am trying to achieve is to open a modal dialog when the user press on one of the items of a FlatList component. The code of this list looks like this:
class MyItem extends React.Component {
_onPress = () => {
this.props.onPressItem(this.props.item);
};
render() {
return(
<TouchableOpacity
{...this.props}
onPress={this._onPress}
>
<Text style={styles.itemText}> {this.props.item.name}</Text>
</TouchableOpacity>
)
}
}
export default class MyList extends React.PureComponent {
constructor(props) {
super(props);
this.state = {
data: {}, // some data correctly loaded
isModalVisible: false
};
};
_onPressItem = (item) => {
this._showModal;
};
_showModal = () => this.setState({ isModalVisible: true })
_keyExtractor = (item, index) => item.id;
_renderItem = ({item}) => (
<MyItem
style={styles.row}
item={item}
onPressItem={this._onPressItem}
/>
);
render() {
return(
<KeyboardAvoidingView behavior="padding" style={styles.container}>
<View style={styles.titleContainer}>
<Text style={styles.title}>Tittle</Text>
</View>
<ScrollView style={styles.container}>
<FlatList
data={this.state.data}
ItemSeparatorComponent = {this._flatListItemSeparator}
renderItem={this._renderItem}
keyExtractor={this._keyExtractor}
/>
</ScrollView>
<MyModal modalVisible={this.state.isModalVisible}/>
</KeyboardAvoidingView>
);
}
}
Styles, FlatList data and some functions have been removed because they are not relevant for this issue.
As you can see, MyModal
component is declared after ScrollView
component. The code is based on the use of react-native Modal component:
export default class MyModal extends Component {
constructor(props) {
super(props);
this.state = {
isModalVisible: props.modalVisible
};
};
_setModalVisible(visible) {
this.setState({modalVisible: visible});
}
render() {
return (
<View>
<Modal
animationType="slide"
transparent={false}
visible={this.state.modalVisible}
onRequestClose={() => {alert("Modal has been closed.")}}
>
<View style={styles.container}>
<View style={styles.innerContainer}>
<Text>Item Detail</Text>
<TouchableHighlight
style={styles.buttonContainer}
onPress={() => { this._setModalVisible(false) }}>
<Text style={styles.buttonText}>Close</Text>
</TouchableHighlight>
</View>
</View>
</Modal>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
padding: 20,
backgroundColor: 'transparent',
},
innerContainer: {
borderRadius: 10,
alignItems: 'center',
backgroundColor: '#34495e',
},
buttonContainer: {
paddingVertical: 15,
marginTop: 20,
backgroundColor: '#2c3e50',
borderRadius: 15
},
buttonText: {
textAlign: 'center',
color: '#ecf0f1',
fontWeight: '700'
},
});
Current behaviour is MyModal
component being displayed when I access to MyList
component for the first time, I can close it and then the FlatList
is there but when a list item is pressed, MyModal
component is not displayed.
How can I manage to hide Modal and open it only when a list item is pressed?
Another doubt related to this is:
How to pass the pressed item object to MyModal
component?
Thanks in advance!
item
through to the modalTo pass the selected item to your modal, you'll need to add it as a prop
on your Modal
component.
You can remember the selected item in MyList
's state:
_onPressItem = (item) => {
this._showModal(item);
};
_showModal = (selectedItem) => this.setState({ isModalVisible: true, selectedItem })
And then pass it through to the modal when you render
it from MyList
:
// ...
</ScrollView>
<MyModal
modalVisible={this.state.isModalVisible}
selectedItem={this.state.selectedItem} />
</KeyboardAvoidingView>
// ...
Currently you have a modal visibility boolean in both MyList
's state (isModalVisible
, which is passed through to MyModal
as the modalVisible
prop) and also in MyModal
's state (modalVisible
). There's no need for the last one - it'll just give you a headache trying to keep them in sync. Just use the props to "control" MyModal
, keeping a single source of truth, and pass a callback to allow MyModal
to tell MyList
that the modal should be dismissed.
// ...
</ScrollView>
<MyModal
modalVisible={this.state.isModalVisible}
selectedItem={this.state.selectedItem}
onDismiss={this._hideModal} />
</KeyboardAvoidingView>
// ...
A new stateless MyModal
:
export default class MyModal extends Component {
render() {
return (
<View>
<Modal
animationType="slide"
transparent={false}
visible={this.props.modalVisible}
onRequestClose={() => { this.props.onDismiss() }}
>
<View style={styles.container}>
<View style={styles.innerContainer}>
<Text>Item Detail</Text>
<TouchableHighlight
style={styles.buttonContainer}
onPress={() => { this.props.onDismiss() }}>
<Text style={styles.buttonText}>Close</Text>
</TouchableHighlight>
</View>
</View>
</Modal>
</View>
);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With