React native - 在 for 循环中一个接一个打开多个模式
React native - open multiple modals one after the other inside for loop
我首先进行 Ajax 调用(对 API),它为我提供了一些数据,成就列表(objects 数组)。我想遍历这个数组,将第一个成就显示为模式,然后单击按钮关闭模式,然后显示下一个(下一个成就)等等。
Ajax调用提供数据:
getAchievements = () => {
fetch(url + '/achievements', {
method: 'get',
headers: {
Accept: 'application/json',
'Content-type': 'application/json'
}
})
.then((data) => data.json())
.then((data) => {
this.props.addData({
achievements: data.achievements
})
if(this.props.store.achievements.length > 0) {
this.setState({
showAchievementModal: true
})
}
})
.catch((error) => {
console.error(error)
})
}
这里我展示模态:
render() {
return (
{this.state.showAchievementModal &&
<Modal
animationType={'fade'}
visible={this.props.store.isModalAchievementVisible}
>
{this.props.store.achievements.map((data,index)=>{
return(
<View key={index}>
<View style={styles.container}>
<Text>{data.title}</Text>
<Text>{data.description}</Text>
<TouchableOpacity onPress={this.closeModal}>
<Text>Collect</Text>
</TouchableOpacity>
</View>
</View>
)
})}
</Modal>
}
)
}
目前所有模态框同时打开。点击收藏按钮后如何一个接一个打开?
问题是您的页面上有多个模态框,它们都使用相同的布尔值来检查是否应呈现它们。最初,showAchievementModal 设置为 true,因此所有模态都被渲染。此外,在 showAchievementModal 中将 showAchievementModal 设置为 false 后,它将永久保持 false,因此不会渲染其他模态。
render() {
return (
{this.state.showAchievementModal &&
<Modal
...
</Modal>
}
)
}
而不是 showAchievementModal 你应该跟踪活动模式的 index。因此,在您从 API 获取成就列表后,将 activeModalIndex 设置为 0。用户关闭第一个模态后,在 closeModal 方法中将 activeModalIndex 设置为 1 ,然后设置在第二个模式关闭后它变为 2 等等。
现在,为了让每个模态框对应一个成就,我们必须将成就数组的每个元素映射到一个模态框,并且只有当对应的索引是活动的时才有条件地渲染它。
render() {
const achievements = this.props.store.achievements;
const { activeModalIndex } = this.state;
return achievements.map((data, index) => activeModalIndex === index &&
<Modal key={index}>
<View>
<View style={styles.container}>
<Text>{data.title}</Text>
<Text>{data.description}</Text>
<TouchableOpacity onPress={this.closeModal}>
<Text>Collect</Text>
</TouchableOpacity>
</View>
</View>
</Modal>
)
}
当用户关闭当前活动模态时,只需增加活动模态的索引,下一个模态就会出现,而不是当前模态。如果新增加的值等于或大于数组长度,则不会呈现任何内容,因此在设置新状态之前无需检查最大索引值。
closeModal = () => {
this.setState(previousState => ({
activeModalIndex: previousState.activeModalIndex + 1,
}))
}
此外,请在呈现列表时阅读有关 the dangers of setting index as key 的内容。如果您碰巧需要按某些 value/priority 排序成就并且用户可以检索他们的多页成就,则可能会导致呈现错误的组件。
这是我的代码的更新版本:
在构造函数中初始化activeModalIndex:
constructor(props) {
super(props)
this.state = {
activeModalIndex: 0
}
}
获得成就:
getAchievements = () => {
if(this.props.store.achievements.length > 0) {
this.setState({
showAchievementModal: true,
activeModalIndex: 0,
})
}
}
渲染函数:
render() {
return this.props.store.achievements.map((data,index) => this.state.activeModalIndex === index &&
<Modal>
<View key={index}>
<View style={styles.container}>
<Text>{data.title}</Text>
<Text>{data.description}</Text>
<TouchableOpacity onPress={this.closeModal}>
<Text>Collect</Text>
</TouchableOpacity>
</View>
</View>
</Modal>
)
}
关闭模式:
closeModal = () => {
const maxIndex = this.props.store.achievements.length - 1
const currentIndex = this.state.activeModalIndex
const isLastModal = currentIndex === maxIndex
const newIndex = isLastModal? -1: currentIndex +1
this.setState({
activeModalIndex: newIndex
})
}
我首先进行 Ajax 调用(对 API),它为我提供了一些数据,成就列表(objects 数组)。我想遍历这个数组,将第一个成就显示为模式,然后单击按钮关闭模式,然后显示下一个(下一个成就)等等。
Ajax调用提供数据:
getAchievements = () => {
fetch(url + '/achievements', {
method: 'get',
headers: {
Accept: 'application/json',
'Content-type': 'application/json'
}
})
.then((data) => data.json())
.then((data) => {
this.props.addData({
achievements: data.achievements
})
if(this.props.store.achievements.length > 0) {
this.setState({
showAchievementModal: true
})
}
})
.catch((error) => {
console.error(error)
})
}
这里我展示模态:
render() {
return (
{this.state.showAchievementModal &&
<Modal
animationType={'fade'}
visible={this.props.store.isModalAchievementVisible}
>
{this.props.store.achievements.map((data,index)=>{
return(
<View key={index}>
<View style={styles.container}>
<Text>{data.title}</Text>
<Text>{data.description}</Text>
<TouchableOpacity onPress={this.closeModal}>
<Text>Collect</Text>
</TouchableOpacity>
</View>
</View>
)
})}
</Modal>
}
)
}
目前所有模态框同时打开。点击收藏按钮后如何一个接一个打开?
问题是您的页面上有多个模态框,它们都使用相同的布尔值来检查是否应呈现它们。最初,showAchievementModal 设置为 true,因此所有模态都被渲染。此外,在 showAchievementModal 中将 showAchievementModal 设置为 false 后,它将永久保持 false,因此不会渲染其他模态。
render() {
return (
{this.state.showAchievementModal &&
<Modal
...
</Modal>
}
)
}
而不是 showAchievementModal 你应该跟踪活动模式的 index。因此,在您从 API 获取成就列表后,将 activeModalIndex 设置为 0。用户关闭第一个模态后,在 closeModal 方法中将 activeModalIndex 设置为 1 ,然后设置在第二个模式关闭后它变为 2 等等。
现在,为了让每个模态框对应一个成就,我们必须将成就数组的每个元素映射到一个模态框,并且只有当对应的索引是活动的时才有条件地渲染它。
render() {
const achievements = this.props.store.achievements;
const { activeModalIndex } = this.state;
return achievements.map((data, index) => activeModalIndex === index &&
<Modal key={index}>
<View>
<View style={styles.container}>
<Text>{data.title}</Text>
<Text>{data.description}</Text>
<TouchableOpacity onPress={this.closeModal}>
<Text>Collect</Text>
</TouchableOpacity>
</View>
</View>
</Modal>
)
}
当用户关闭当前活动模态时,只需增加活动模态的索引,下一个模态就会出现,而不是当前模态。如果新增加的值等于或大于数组长度,则不会呈现任何内容,因此在设置新状态之前无需检查最大索引值。
closeModal = () => {
this.setState(previousState => ({
activeModalIndex: previousState.activeModalIndex + 1,
}))
}
此外,请在呈现列表时阅读有关 the dangers of setting index as key 的内容。如果您碰巧需要按某些 value/priority 排序成就并且用户可以检索他们的多页成就,则可能会导致呈现错误的组件。
这是我的代码的更新版本:
在构造函数中初始化activeModalIndex:
constructor(props) {
super(props)
this.state = {
activeModalIndex: 0
}
}
获得成就:
getAchievements = () => {
if(this.props.store.achievements.length > 0) {
this.setState({
showAchievementModal: true,
activeModalIndex: 0,
})
}
}
渲染函数:
render() {
return this.props.store.achievements.map((data,index) => this.state.activeModalIndex === index &&
<Modal>
<View key={index}>
<View style={styles.container}>
<Text>{data.title}</Text>
<Text>{data.description}</Text>
<TouchableOpacity onPress={this.closeModal}>
<Text>Collect</Text>
</TouchableOpacity>
</View>
</View>
</Modal>
)
}
关闭模式:
closeModal = () => {
const maxIndex = this.props.store.achievements.length - 1
const currentIndex = this.state.activeModalIndex
const isLastModal = currentIndex === maxIndex
const newIndex = isLastModal? -1: currentIndex +1
this.setState({
activeModalIndex: newIndex
})
}