React native - открывайте несколько модалов один за другим внутри цикла for - PullRequest
1 голос
/ 09 марта 2019

Сначала я делаю 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>
        }
    )
}

В данный момент все модалы открываются одновременно.Как я могу открыть их один за другим после нажатия кнопки «Собрать»?

Ответы [ 2 ]

0 голосов
/ 10 марта 2019

Это обновленная версия моего кода, которая работает:

Инициализация 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
  })
}
0 голосов
/ 09 марта 2019

Проблема в том, что у вас есть несколько модалов на вашей странице, и все они используют один и тот же логический параметр, чтобы проверить, следует ли их визуализировать. Изначально showAchievementModal имеет значение true, поэтому все модалы отображаются. Кроме того, после установки showAchievementModal в false в closeModal , он будет постоянно оставаться ложным, поэтому дополнительные модалы не будут отображаться.

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

Вместо showAchievementModal вы должны отслеживать index активного модального режима. Итак, после получения списка достижений из вашего API, установите activeModalIndex на 0 . После того как пользователь отклоняет этот первый модальный режим, установите activeModalIndex на 1 в методе closeModal , а затем установите его на 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,
    }))
}

Также, пожалуйста, прочитайте о опасностях установки индекса в качестве ключа при рендеринге списков. Если вам нужно упорядочить достижения по некоторому значению / приоритету, и пользователи могут получить несколько страниц своих достижений, это может вызвать рендеринг неправильных компонентов.

...