React Native close Modal, который открывается другим компонентом

Здравствуйте, я новичок в React Native, и в настоящее время у меня проблема с моим модальным компонентом. Мой модальный компонент имеет два реквизита: gameData и isModalVisible. В Home.js модальное свойство isModalVisible имеет значение переменной состояния isVisible, которая изменяется на true при нажатии определенной TouchableOpacity. Затем внутри моего FeaturedGameModal.js isModalVisible устанавливается из реквизита. У меня проблема с закрытием модального окна. Открытие модального окна таким образом работает нормально, но как мне закрыть модальное окно, поскольку его видимость контролируется реквизитами, которые находятся в Home.js? Любая помощь будет принята с благодарностью. Я работаю над этим уже два дня, и это сводит меня с ума. Спасибо! Я включу два своих файла на случай, если вы захотите более внимательно изучить мой код.

Главная.js:

import React from 'react';
import {
  View,
  Text,
  Image,
  SafeAreaView,
  TouchableOpacity,
  ActivityIndicator,
  Linking,
  ScrollView,
  TouchableHighlight,
} from 'react-native';
import {homeStyles} from '../styles/homeStyles';
import {styles} from '../styles/styles';
import {createIconSetFromIcoMoon} from 'react-native-vector-icons';
import icoMoonConfig from '../../assets/fonts/selection.json';
import {fetchData} from '../functions/fetch';
import Modalz from '../modals/FeaturedGameModal';

const Icon = createIconSetFromIcoMoon(icoMoonConfig);

class Home extends React.Component {
  myData = {};

  constructor(props) {
    super(props);
    this.state = {
      error: false,
      isFetching: true,
      featuredGameModal: false,
      isVisible: false,
    };
  }

  handleFeaturedGame = async () => {
    this.setState({}, async () => {
      try {
        const featureGameData = await fetchData(
          'http://dev.liberty.edu/templates/flames/json/json_appHomeFeed.cfm',
        );

        this.setState({
          error: false,
          featuredGameData: featureGameData,
          isFetching: false,
        });
      } catch (e) {
        this.setState({
          error: true,
        });
        console.info(e.message);
      }
    });
  };

  handleFeaturedModal() {
    this.setState({featuredGameModal: false});
  }

  componentDidMount() {
    this.handleFeaturedGame();
  }

  render() {
    const {featuredGameData} = this.state;
    return this.state.isFetching ? (
      <View style = {styles.center}>
        <ActivityIndicator size = "large" color = "#AE0023" />
      </View>
    ) : (
      <ScrollView>
        <SafeAreaView>
          <View style = {homeStyles.featuredGameContainer}>
            <View style = {homeStyles.centerHor}>
              <Image
                style = {homeStyles.logo}
                source = {require('../../assets/images/FlamesLogo.png')}
              />
            </View>
            <View style = {homeStyles.gameTimeContainer}>
              <Text style = {homeStyles.gameTime}>
                {featuredGameData.featuredGame.eventdate}
              </Text>
              <Text style = {homeStyles.gameTime}>
                {featuredGameData.featuredGame.eventtime}
              </Text>
            </View>
            <TouchableOpacity
              activeOpacity = {0.6}
              onPress = {() => {
                this.setState({isVisible: true});
              }}>
              <View style = {homeStyles.contentContainer}>
                <View style = {homeStyles.contentLeft}>
                  <Text style = {homeStyles.teamText}>
                    {featuredGameData.featuredGame.teamname}
                  </Text>
                  <Text style = {homeStyles.opponentText}>
                    vs {featuredGameData.featuredGame.opponent}
                  </Text>
                  <Text style = {homeStyles.locationText}>
                    <Icon size = {12} name = {'location'} />
                    &nbsp;{featuredGameData.featuredGame.location}
                  </Text>
                </View>
                <View style = {homeStyles.contentRight}>
                  <Image
                    style = {homeStyles.opponentLogo}
                    source = {{
                      uri: featuredGameData.featuredGame.OpponentLogoFilename,
                    }}
                  />
                </View>
              </View>
            </TouchableOpacity>
            <View style = {homeStyles.allContent}>
              <Modalz
                gameData = {this.state.featuredGameData.featuredGame}
                isModalVisible = {this.state.isVisible}
              />
              <View style = {homeStyles.contentContainerBottom}>
                <View style = {homeStyles.contentLeft}>
                  <TouchableOpacity
                    style = {homeStyles.buyTicketBtn}
                    onPress = {() =>
                      Linking.openURL(featuredGameData.featuredGame.buyTickets)
                    }>
                    <Text style = {homeStyles.buyTicketBtnText}>Buy Tickets</Text>
                  </TouchableOpacity>
                </View>
                <View style = {homeStyles.liveContainer}>
                  <Text style = {homeStyles.live}>Experience Live:</Text>
                  <View style = {homeStyles.liveIconsContainer}>
                    <Icon
                      style = {{color: '#FFF', marginRight: 4}}
                      size = {15}
                      name = {'radio'}
                    />
                    <Icon style = {{color: '#FFF'}} size = {12} name = {'LFSN'} />
                  </View>
                </View>
              </View>
            </View>
          </View>
          <View style = {homeStyles.newsContainer}>
            {featuredGameData.News.map((item, key) => (
              <View
                key = {key}
                style = {[homeStyles.centerHor, homeStyles.newsCard]}>
                <Image
                  style = {homeStyles.newsImage}
                  source = {{
                    uri: item.Thumbnail,
                  }}
                />
                <Text style = {homeStyles.headline}>{item.Headline}</Text>
                <View style = {homeStyles.teamNameView}>
                  <Text style = {homeStyles.teamNameText}>{item.teamname}</Text>
                  <Text>{item.GameDate}</Text>
                </View>
              </View>
            ))}
          </View>
        </SafeAreaView>
      </ScrollView>
    );
  }
}

export default Home;

FeaturedGameModal.js:

import React from 'react';
import {
  Alert,
  Modal,
  StyleSheet,
  Text,
  TouchableHighlight,
  View,
  Image,
  Dimensions,
  TouchableOpacity,
  SafeAreaView,
} from 'react-native';

import {createIconSetFromIcoMoon} from 'react-native-vector-icons';
import icoMoonConfig from '../../assets/fonts/selection';
import {homeStyles} from '../styles/homeStyles';

const Icon = createIconSetFromIcoMoon(icoMoonConfig);

const windowWidth = Dimensions.get('window').width;

export default class Modalz extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      teamName: props.gameData.teamname,
      opponentName: props.gameData.opponent,
      eventDate: props.gameData.eventdate,
      liveAudioURL: props.gameData.LiveAudioURL,
      liveStatsURL: props.gameData.LiveStatsURL,
      videoURL: props.gameData.VideoURL,
      opponentLogoURL: props.gameData.OpponentLogoFilename,
    };
  }

  render() {
    const {
      opponentName,
      teamName,
      eventDate,
      opponentLogoURL,
      liveStatsURL,
      liveAudioURL,
      videoURL,
      location,
    } = this.state;

    const {isModalVisible} = this.props;

    return (
      <View>
        <View style = {styles.centeredView}>
          <Modal
            animationType = "slide"
            transparent = {true}
            visible = {isModalVisible}
            onRequestClose = {() => {
              Alert.alert('Modal has been closed.');
            }}>
            <SafeAreaView style = {{flex: 1, backgroundColor: 'transparent'}}>
              <View style = {styles.centeredView}>
                <View style = {styles.modalView}>
                  <Icon
                    style = {styles.closeButton}
                    size = {25}
                    name = {'x'}
                    onPress = {() => {}}
                  />

                  <Text style = {styles.upcomingGameTitle}>
                    {teamName} vs {opponentName}
                  </Text>
                  <Text style = {styles.upcomingGameSubtitle}>{eventDate}</Text>
                  <View style = {styles.facingLogosBlock}>
                    <View style = {styles.leftTeamBlock} />
                    <View style = {styles.rightTeamBlock} />
                    <View style = {styles.vsTextWrapper}>
                      <Text style = {styles.vsText}>VS</Text>
                    </View>
                    <View style = {styles.logoWrapper}>
                      <Image
                        style = {styles.facingLogoImg}
                        source = {{
                          uri:
                            'https://www.liberty.edu/templates/flames/images/flamesMonogram.png',
                        }}
                      />
                      <Image
                        style = {styles.facingLogoImg}
                        source = {{uri: opponentLogoURL}}
                      />
                    </View>
                  </View>

                  <View>
                    <TouchableOpacity style = {styles.buyTicketBtn}>
                      <Text style = {styles.buyTicketBtnText}>Buy Tickets</Text>
                    </TouchableOpacity>
                  </View>
                  <View style = {styles.buttonRow}>
                    <TouchableOpacity
                      style = {{...styles.iconButton, ...styles.iconButtonLeft}}>
                      <Icon
                        style = {styles.iconButtonIcon}
                        size = {25}
                        name = {'flag'}
                        onPress = {() => {
                          this.toggleModal(!this.state.modalVisible);
                        }}
                      />
                      <Text style = {styles.iconButtonText}>Game Day</Text>
                    </TouchableOpacity>

                    <TouchableOpacity
                      style = {{...styles.iconButton, ...styles.iconButtonRight}}>
                      <Icon
                        style = {styles.iconButtonIcon}
                        size = {25}
                        name = {'stats'}
                        onPress = {() => {
                          this.toggleModal(!this.state.modalVisible);
                        }}
                      />
                      <Text style = {styles.iconButtonText}>Live Stats</Text>
                    </TouchableOpacity>
                  </View>
                  <View style = {styles.liveLinkBlock}>
                    <View style = {styles.liveLinkLeft}>
                      <Icon
                        style = {styles.iconButtonIcon}
                        size = {18}
                        name = {'LFSN'}
                      />
                      <Text>The Journey 88.3 FM</Text>
                    </View>
                    <TouchableOpacity style = {styles.liveButton}>
                      <Text style = {styles.liveButtonText}>Listen Live</Text>
                    </TouchableOpacity>
                  </View>
                  <View style = {styles.liveLinkBlock}>
                    <View style = {styles.liveLinkLeft}>
                      <Icon
                        style = {styles.iconButtonIcon}
                        size = {18}
                        name = {'espn3'}
                      />
                      <Text>LFSN TV Production</Text>
                    </View>
                    <TouchableOpacity style = {styles.liveButton}>
                      <Text style = {styles.liveButtonText}>Watch Live</Text>
                    </TouchableOpacity>
                  </View>
                </View>
              </View>
            </SafeAreaView>
          </Modal>
        </View>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  centeredView: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
  modalView: {
    flex: 1,
    alignSelf: 'stretch',
    backgroundColor: 'white',
    borderTopLeftRadius: 20,
    borderTopRightRadius: 20,
    paddingTop: 14,
    alignItems: 'center',
    shadowColor: '#000',
    shadowOffset: {
      width: 0,
      height: 2,
    },
    shadowOpacity: 0.25,
    shadowRadius: 3.84,
    elevation: 5,
  },
  openButton: {
    backgroundColor: '#F194FF',
    borderRadius: 20,
    padding: 10,
    elevation: 2,
  },
  closeButton: {
    position: 'absolute',
    right: 16,
    top: 16,
    color: '#000',
  },
  closeText: {
    color: '#000',
    fontWeight: 'bold',
    textAlign: 'center',
    fontSize: 20,
  },
  upcomingGameTitle: {
    color: '#19191A',
    fontSize: 18,
    fontWeight: 'bold',
  },
  upcomingGameSubtitle: {
    color: '#747676',
    fontSize: 13,
    fontWeight: 'bold',
    marginBottom: 16,
  },
  modalText: {
    marginBottom: 15,
    textAlign: 'center',
  },
  facingLogosBlock: {
    flexDirection: 'row',
    position: 'relative',
    alignItems: 'center',
  },
  facingLogoImg: {
    width: 100,
    height: 100,
    resizeMode: 'contain',
    flex: 1,
  },
  leftTeamBlock: {
    width: 0,
    height: 0,
    backgroundColor: 'transparent',
    borderStyle: 'solid',
    borderRightWidth: 35,
    borderTopWidth: 185,
    borderRightColor: 'transparent',
    borderTopColor: '#AE0023',
    borderLeftColor: '#AE0023',
    borderLeftWidth: windowWidth / 2,
    left: 15,
    zIndex: -1,
    position: 'relative',
  },
  rightTeamBlock: {
    width: 0,
    height: 0,
    backgroundColor: 'transparent',
    borderStyle: 'solid',
    borderLeftWidth: 35,
    borderBottomWidth: 185,
    borderBottomColor: '#461964',
    borderRightColor: '#461964',
    borderLeftColor: 'transparent',
    borderRightWidth: windowWidth / 2,
    right: 15,
    zIndex: -1,
    position: 'relative',
  },
  vsTextWrapper: {
    position: 'absolute',
    top: 0,
    left: 0,
    right: 0,
    bottom: 0,
    justifyContent: 'center',
    alignItems: 'center',
  },
  vsText: {
    color: '#000000',
    backgroundColor: '#FFFFFF',
    padding: 5,
    fontWeight: 'bold',
  },
  logoWrapper: {
    position: 'absolute',
    width: windowWidth,
    height: 185,
    top: 0,
    left: 35,
    flexDirection: 'row',
    alignItems: 'center',
  },
  buyTicketBtn: {
    marginTop: 24,
    backgroundColor: '#AE0023',
    borderRadius: 4,
    paddingVertical: 20,
    paddingHorizontal: 12,
    width: windowWidth - 24,
  },
  buyTicketBtnText: {
    fontSize: 21,
    color: '#fff',
    fontWeight: 'bold',
    alignSelf: 'center',
    textTransform: 'uppercase',
  },
  buttonRow: {
    paddingVertical: 24,
    paddingHorizontal: 12,
    flexDirection: 'row',
    justifyContent: 'space-between',
    alignItems: 'center',
  },
  iconButton: {
    backgroundColor: '#F0F3F5',
    borderRadius: 4,
    paddingVertical: 14,
    alignItems: 'center',
    justifyContent: 'center',
    flexDirection: 'row',
    flex: 1,
  },
  iconButtonText: {
    color: '#19191A',
    fontWeight: 'bold',
    fontSize: 16,
    marginLeft: 10,
  },
  iconButtonIcon: {
    color: '#000',
  },
  iconButtonLeft: {
    marginRight: 6,
  },
  iconButtonRight: {
    marginLeft: 6,
  },
  liveLinkBlock: {
    padding: 12,
    borderStyle: 'solid',
    borderTopColor: '#F0F3F5',
    borderTopWidth: 1,
    alignItems: 'center',
    justifyContent: 'center',
    flexDirection: 'row',
  },
  liveButton: {
    backgroundColor: '#F0F3F5',
    borderRadius: 4,
    paddingVertical: 14,
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
  liveButtonText: {
    color: '#19191A',
    fontWeight: 'bold',
    fontSize: 16,
  },
  liveLinkLeft: {
    flex: 2,
  },
});
Умерло ли Create-React-App?
Умерло ли Create-React-App?
В этом документальном фильме React.dev мы исследуем, мертв ли Create React App (CRA) и какое будущее ждет этот популярный фреймворк React.
Освоение React Native: Пошаговое руководство для начинающих
Освоение React Native: Пошаговое руководство для начинающих
React Native - это популярный фреймворк с открытым исходным кодом, используемый для разработки мобильных приложений. Он был разработан компанией...
В чем разница между react native и react ?
В чем разница между react native и react ?
React и React Native - два популярных фреймворка для создания пользовательских интерфейсов, но они предназначены для разных платформ. React - это...
От React к React Native: Руководство для начинающих по разработке мобильных приложений с использованием React
От React к React Native: Руководство для начинающих по разработке мобильных приложений с использованием React
Если вы уже умеете работать с React, создание мобильных приложений для iOS и Android - это новое приключение, в котором вы сможете применить свои...
Хуки React: что это такое и как их использовать
Хуки React: что это такое и как их использовать
Хуки React - это мощная функция библиотеки React, которая позволяет разработчикам использовать состояние и другие возможности React без написания...
1
0
666
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вы должны создать функцию hideModal в Home.js, а затем передать ее компоненту Modalz.

В Home.js добавьте эту функцию:

hideModalz = () => {
    this.setState({isVisible: true});
}

И передайте эту функцию реквизитам Modalz:

<Modalz
    gameData = {this.state.featuredGameData.featuredGame}
    isModalVisible = {this.state.isVisible}
    hide = {hideModalz}
/>

В Modalz вызовите this.props.hide();, если хотите скрыть модальное окно.

Спасибо! Моя функция, переданная модальному модулю, немного отличается, но это заставило меня двигаться в правильном направлении. Я ценю вашу помощь!

Jeremy Brooks 13.12.2020 20:35

Другие вопросы по теме