简体   繁体   English

React Native-在for循环中一个接一个地打开多个模态

[英]React native - open multiple modals one after the other inside for loop

I first make an Ajax call (to an API) which provides me some data, a list of achievements (array of objects). 我首先进行Ajax调用(对API),该调用向我提供了一些数据,成就列表(对象数组)。 I would like to loop through this array, show the first achievement as a Modal and on click of a button close the modal then show the next one (next achievement) and so on. 我想遍历此数组,将第一个成就显示为模态,单击按钮关闭模态,然后显示下一个成就(下一个成就),依此类推。

Ajax call providing the data: 提供数据的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)
    })
}

Here I show the modals: 在这里,我展示了模态:

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>
        }
    )
}

At the moment all the Modals open at the same time. 此刻所有模态同时打开。 How could I open them one after the other after clicking the Collect button? 单击“收集”按钮后,如何依次打开它们?

The problem is that you have multiple Modals on your page and they all use the same boolean to check if they should be rendered. 问题是您的页面上有多个模式,并且它们都使用相同的布尔值来检查是否应该渲染它们。 Initially, showAchievementModal is set to true, so all modals are rendered. 最初,将showAchievementModal设置为true,以便呈现所有模态。 Furthermore, after you set showAchievementModal to false in closeModal , it will permanently stay false, so no additional modals will get rendered. 此外,在closeModal中将showAchievementModal设置为false后,它将永久保持为false,因此不会呈现任何其他模式。

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

Instead of showAchievementModal you should be keeping track of index of active modal. 而不是showAchievementModal,您应该跟踪活动模式的索引 So, after you fetch the list of achievements from your API, set the activeModalIndex to 0 . 因此,从API获取成就列表之后,将activeModalIndex设置为0 After the user dismisses this first modal, set the activeModalIndex to 1 inside the closeModal method, then set it to 2 after the second modal is closed and so on. 用户关闭第一个模态后,在closeModal方法中将activeModalIndex设置为1 ,然后在关闭第二个模态后将activeModalIndex设置为2 ,依此类推。

Now, for every modal to correspond to a single achievement, we must map each element of the achievements array to a single Modal and conditionally render it only if its corresponding index is the active one. 现在,对于每个与单个成就相对应的模态,我们必须将成就数组的每个元素映射到一个模态,并且仅在其对应的索引为活动索引时有条件地对其进行渲染。

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>
    )
}

When the users dismisses the currently active modal, simply increment the index of the active modal and the next modal will appear instead of the current one. 当用户关闭当前有效模态时,只需增加有效模态的索引,下一个模态将代替当前模态出现。 If the new incremented value is equal or larger than the array length, nothing will get rendered, so no need to check for max index value before setting new state. 如果新的递增值等于或大于数组长度,则不会呈现任何内容,因此在设置新状态之前无需检查最大索引值。

closeModal = () => {   
    this.setState(previousState => ({
      activeModalIndex: previousState.activeModalIndex + 1,
    }))
}

Also, please read about the dangers of setting index as key when rendering lists. 另外,请阅读渲染列表时将index设置为键的危险 If you happen to need ordering achievements by some value/priority and users can retrieve multiple pages of their achievements, it might cause rendering wrong components. 如果您碰巧需要按某个值/优先级对成就进行排序,并且用户可以检索其成就的多个页面,则可能会导致呈现错误的组件。

This is the updated version of my code that works: 这是有效的我的代码的更新版本:

Initialising activeModalIndex in the constructor: 在构造函数中初始化activeModalIndex:

constructor(props) {
  super(props)

  this.state = {
    activeModalIndex: 0
  }
}

Get achievements: 获得成就:

getAchievements = () => {
  if(this.props.store.achievements.length > 0) {
    this.setState({
      showAchievementModal: true,
      activeModalIndex: 0,
    })
  }
}

Render function: 渲染功能:

 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>
  )
}

Close 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
  })
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM