[英]How to open Modal with item information when clicking a FlatList element?
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. 我要实现的目标是,当用户按下FlatList组件之一时,打开一个模式对话框。 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. 样式,FlatList数据和某些功能已删除,因为它们与此问题无关。
As you can see, MyModal
component is declared after ScrollView
component. 如您所见, MyModal
组件在ScrollView
组件之后声明。 The code is based on the use of react-native Modal component: 该代码基于使用react-native Modal组件:
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. 目前的行为是MyModal
当我访问显示组件MyList
组件的第一次,我可以关闭它,然后FlatList
是存在的,但是当按下列表项, MyModal
不显示组件。
How can I manage to hide Modal and open it only when a list item is pressed? 仅在按下列表项时,如何才能隐藏Modal并打开它?
Another doubt related to this is: 与此相关的另一个疑问是:
How to pass the pressed item object to MyModal
component? 如何将按下的项目对象传递给MyModal
组件?
Thanks in advance! 提前致谢!
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,
selectedItem: null
};
};
_onPressItem = (item) => {
this._showModal(item);
};
_hideMyModal = () => {
this.setState({isModalVisible: false})
}
_showModal = (item) => this.setState({ isModalVisible: true,
selectedItem: item })
_keyExtractor = (item, index) => item.id;
_renderItem = ({item}) => (
<MyItem
style={styles.row}
item={item}
onPressItem={() => this._onPressItem(item)}
/>
);
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>
{ this.state.isModalVisible && <MyModal selectedItem={this.state.selectedItem} modalVisible={this.state.isModalVisible} hideModal={this_hideMyModal} /> }
</KeyboardAvoidingView>
);
}
}
When you press the item in FlatList, just set it in the state and pass it as a prop to MyModal component(pretty self explanatory). 当您在FlatList中按下该项目时,只需将其设置为状态,然后将其作为道具传递给MyModal组件即可。
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.isModalVisible}
onRequestClose={() => {alert("Modal has been closed.")}}
>
<View style={styles.container}>
<View style={styles.innerContainer}>
<Text>Item Detail</Text>
<TouchableHighlight
style={styles.buttonContainer}
onPress={() => { this.props.hideModal() }}>
<Text style={styles.buttonText}>Close</Text>
</TouchableHighlight>
</View>
</View>
</Modal>
</View>
);
}
}
In your previous code in MyModal
you were doing this --> onPress={() => { this._setModalVisible(false) }}>
which will hide the modal in the MyModal
class but MyModal
is still rendered in the MyList
class. 在以前的代码MyModal
你这样做- > onPress={() => { this._setModalVisible(false) }}>
这将隐藏在该模式MyModal
类,但MyModal
仍然在呈现MyList
类。 So you might be unable to click the FlatList item again. 因此,您可能无法再次单击FlatList项目。 I passed a prop hideModal
which will remove the MyModal
component from the MyList
. 我通过一个道具hideModal
这将删除MyModal
从组件MyList
。 In my revised code you don't need to pass modalVisible
prop also, but its up to you for that. 在我的修订代码中,您也不需要通过modalVisible
,但是这取决于您。
item
through to the modal 将item
传递给模态 To pass the selected item to your modal, you'll need to add it as a prop
on your Modal
component. 要将所选项目传递给模态,您需要将其作为prop
添加到Modal
组件上。
You can remember the selected item in MyList
's state: 您可以记住处于MyList
状态的所选项目:
_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
: 然后从MyList
render
它时, render
其传递给模态:
// ...
</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
). 目前,你有两种模态的知名度布尔MyList
的状态( isModalVisible
,这是通过传递给MyModal
作为modalVisible
道具)以及在MyModal
的状态( 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. 只需使用道具“ 控制 ” MyModal
,保持真相的单一来源,并通过回调允许MyModal
告诉MyList
该模式应予以驳回。
// ...
</ScrollView>
<MyModal
modalVisible={this.state.isModalVisible}
selectedItem={this.state.selectedItem}
onDismiss={this._hideModal} />
</KeyboardAvoidingView>
// ...
A new stateless MyModal
: 一个新的无状态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>
);
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.