2

我首先进行 Ajax 调用(对 API),它为我提供了一些数据、成就列表(对象数组)。我想遍历这个数组,将第一个成就显示为模态,然后单击按钮关闭模态,然后显示下一个(下一个成就)等等。

提供数据的 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>
        }
    )
}

目前所有的Modal同时打开。单击“收集”按钮后,如何一个接一个地打开它们?

4

2 回答 2

2

这是我工作的代码的更新版本:

在构造函数中初始化 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
  })
}
于 2019-03-10T18:56:34.093 回答
1

问题是您的页面上有多个模态框,它们都使用相同的布尔值来检查是否应该呈现它们。最初,showAchievementModal设置为 true,因此所有模态都被渲染。此外,在 closeModal 中将 showAchievementModal 设置false后,它将永久保持为 false,因此不会呈现其他模式。

render() {
    return (
        {this.state.showAchievementModal &&
          <Modal
             ...          
          </Modal>
        }
    )
}

而不是showAchievementModal您应该跟踪活动模式的索引。因此,在您从 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,
    }))
}

另外,请阅读在渲染列表时将 index 设置为 key 的危险。如果您碰巧需要按某个值/优先级对成就进行排序,并且用户可以检索其成就的多个页面,则可能会导致渲染错误的组件。

于 2019-03-09T15:26:24.897 回答