代码之家  ›  专栏  ›  技术社区  ›  ewizard

React Native-无法使用条件

  •  -1
  • ewizard  · 技术社区  · 6 年前

    我有这段代码,我试图呈现一个元素:

    render() {
        //console.log('this.state.showRespondTo:',this.state.showRespondTo);
        return (
          <View style={{flex:1}}>
            {this.displayMessage()}
            <TouchableWithoutFeedback onPress={Keyboard.dismiss}>
              <View style={styles.container}>
                <MultiSelectList
                  style={{backgroundColor: '#ffe4c4'}}
                  data={this.state.items}
                  renderItem={this.renderListItems}
                  numColumns={2}
                  contentContainerStyle={{}}
                  onEndReachedThreshold={0.5}
                  maxToRenderPerBatch={2}
                  initialNumToRender={4}
                  ListHeaderComponent={this.renderHeader}
                  getItemLayout={(data, index) => (
                    {length: Dimensions.get('window').height/2, offset: Dimensions.get('window').height/2 * index, index}
                  )}
                  backgroundColor={this.state.backgroundColor}
                  //contentContainerStyle={{backgroundColor: '#1e4683'}}
                />
              </View>
            </TouchableWithoutFeedback>
          </View>
        );
    }
    
    displayMessage() {
        if(this.state.showRespondTo) {
          console.log('this.state.showRespondTo:', this.state.showRespondTo);
          return ( <RespondToInquiry/> )
        }
    }
    

    这就是 RespondToInquiry

    import React, { Component } from 'react'
    import {
      Text,
      TextInput,
      TouchableOpacity,
      TouchableHighlight,
      TouchableWithoutFeedback,
      View,
      Dimensions,
      Keyboard
    } from 'react-native'
    import { Calendar, CalendarList, Agenda } from 'react-native-calendars';
    import { Map } from 'immutable';
    import Modal from 'react-native-modal';
    import firebase from 'react-native-firebase';
    
    export default class RespondToInquiry extends React.PureComponent {
      constructor() {
        super()
        this.state = {
          _markedDates: {},
          //_selectedDay: new Date().dateString,
          modalVisible: false,
          message: 'Hi, I would like to rent an item from you.',
          rentButtonBackground: '#6de3dc',
          datesArray: []
        }
    
        this.onDayPress = this.onDayPress.bind(this)
      }
    
      /*initialState = {
          [new Date()]: { 'selected': false, 
                            customStyles: {
                            container: {
                              backgroundColor: '#6de3dc',
                            },
                            text: {
                              color: 'white',
                              fontWeight: 'bold'
                            },
                          },
                        }
      }*/
    
      showCalendar = () => {
        return (
          <Calendar
            style={{
              borderWidth: 0,
              borderRadius: 4,
            }}
            theme={{
              todayTextColor: '#6de3dc',
              selectedDayBackgroundColor: '#6de3dc',
            }}
            markingType={'custom'}
            markedDates={this.state._markedDates}
            // Initially visible month. Default = Date()
            // Minimum date that can be selected, dates before minDate will be grayed out. Default = undefined
            minDate={new Date()}
            // Maximum date that can be selected, dates after maxDate will be grayed out. Default = undefined
            // Handler which gets executed on day press. Default = undefined
            onDayPress={day => this.onDayPress(day)}
            // Handler which gets executed on day long press. Default = undefined
            onDayLongPress={day => {
              console.log('selected day', day)
            }}
            // Month format in calendar title. Formatting values: http://arshaw.com/xdate/#Formatting
            monthFormat={'MMM d, yyyy'}
            // Handler which gets executed when visible month changes in calendar. Default = undefined
            onMonthChange={month => {
              console.log('month changed', month)
            }}
            // Hide month navigation arrows. Default = false
            //hideArrows={true}
            // Replace default arrows with custom ones (direction can be 'left' or 'right')
            //renderArrow={(direction) => (<Arrow />)}
            // Do not show days of other months in month page. Default = false
            hideExtraDays={true}
            // If hideArrows=false and hideExtraDays=false do not switch month when tapping on greyed out
            // day from another month that is visible in calendar page. Default = false
            //disableMonthChange={true}
            // If firstDay=1 week starts from Monday. Note that dayNames and dayNamesShort should still start from Sunday.
            firstDay={0}
            // Hide day names. Default = false
            //hideDayNames={true}
            // Show week numbers to the left. Default = false
            //showWeekNumbers={true}
            // Handler which gets executed when press arrow icon left. It receive a callback can go back month
            onPressArrowLeft={substractMonth => substractMonth()}
            // Handler which gets executed when press arrow icon left. It receive a callback can go next month
            onPressArrowRight={addMonth => addMonth()}
          />
        )
      }
    
      onDayPress = (day) => {
          const _selectedDay = day.dateString;
    
          let marked = true;
          if (this.state._markedDates[_selectedDay]) {
            // Already in marked dates, so reverse current marked state
            marked = !this.state._markedDates[_selectedDay].selected;
            console.log('marked:', marked);
    
            // Create a new object using object property spread since it should be immutable
            // Reading: https://davidwalsh.name/merge-objects
            const updatedMarkedDates = {...this.state._markedDates, ...{ [_selectedDay]: { 'selected': marked, 
                                                                                            customStyles: {
                                                                                            container: {
                                                                                              backgroundColor: '#6de3dc',
                                                                                            },
                                                                                            text: {
                                                                                              color: 'white',
                                                                                              fontWeight: 'bold'
                                                                                            },
                                                                                          }, 
                                      } } }
    
            // Triggers component to render again, picking up the new state
            this.setState({ _markedDates: updatedMarkedDates }, () => {
              console.log('updatedMarkedDates:', this.state._markedDates);
            });
          }
          else {
            // Create a new object using object property spread since it should be immutable
            // Reading: https://davidwalsh.name/merge-objects
            const updatedMarkedDates = {...this.state._markedDates, ...{ [_selectedDay]: { 'selected': true, 
                                                                                            customStyles: {
                                                                                            container: {
                                                                                              backgroundColor: '#6de3dc',
                                                                                            },
                                                                                            text: {
                                                                                              color: 'white',
                                                                                              fontWeight: 'bold'
                                                                                            },
                                                                                          }, 
                                      } } }
    
            // Triggers component to render again, picking up the new state
            this.setState({ _markedDates: updatedMarkedDates }, () => {
              console.log('updatedMarkedDates:', this.state._markedDates);
            });
          }
      }
    
      waitToStoreDates = () => new Promise((resolve) => {
        let x = 0;
        let datesArray = [];
        for(date in this.state._markedDates) {
          console.log("Date Object: ",date);
          if(this.state._markedDates[date].selected) {
            datesArray.push(date);
          }
          x++;
        }
    
        if(x == Object.keys(this.state._markedDates).length) {
          console.log("x:",x);
          console.log('datesArray in waitToStoreDates:', datesArray);
          this.state.datesArray = datesArray;
          resolve();
        }
      })
    
      async processMarkedDates() {
        await this.waitToStoreDates();
      }
    
      setModalVisible(visible) {
        this.setState({ modalVisible: visible })
      }
    
      componentDidUpdate(prevProps, prevState, snapshot) {
        console.log('componentDidUpdate in InitiateRent:', this.props, prevProps, prevState, snapshot)
      }
    
      _renderModalContent = () => (
        <TouchableWithoutFeedback onPress={() => {console.log('tapped')}}>
          <View
            style={{
              paddingTop: 5,
              paddingBottom: 10,
              paddingLeft: 10,
              paddingRight: 10,
              marginTop: 0,
              flex: 1,
              width: Dimensions.get('window').width
            }}>
            <View style={{ flexDirection: 'column', justifyContent: 'space-between', flex: 1 }}>
              <View style={{ flexDirection: 'column', flex: 1 }}>
                <Text
                  style={{
                    flex: 0,
                    width: Dimensions.get('window').width,
                    color: 'white',
                    fontWeight: '700',
                    marginBottom: 5,
                  }}>
                  Date(s) Needed:
                </Text>
                {this.showCalendar()}
              </View>
              <View style={{ flexDirection: 'column', flex: 0.2, marginBottom: 10 }}>
                <TextInput
                  style={{
                    width: 280,
                    flex: 1,
                    borderColor: 'gray',
                    borderWidth: 1,
                    backgroundColor: '#ffffff',
                    paddingLeft: 5,
                    borderRadius: 4,
                  }}
                  onChangeText={text => this.setState({ message: text })}
                  value={this.state.message}
                  multiline={true}
                  numberOfLines={2}
                />
              </View>
              <View style={{ flex: 0.1, borderRadius: 4, borderWidth: 0 }}>
                <TouchableOpacity
                  activeOpacity={1}
                  style={{
                    backgroundColor: this.state.rentButtonBackground,
                    flex: 1,
                    justifyContent: 'center',
                    alignItems: 'center',
                    width: 280,
                    borderRadius: 4,
                    borderWidth: 0,
                  }}
                  onPress={() => {
                    this.setState({ rentButtonBackground: '#94ebe6' })
    
                    setTimeout(() => {
                      this.setState({ rentButtonBackground: '#6de3dc' })
    
                      let timestamp = new Date().getTime().toString();
    
                      this.processMarkedDates();
                      console.log("this.state.datesArray", this.state.datesArray);
    
                      dataChat = {
                        "title": "Rental Inquiry",
                        "lastMessage": this.state.message,
                        "timestamp": timestamp
                      }
    
                      dataMessage = {}
                      dataMessage[timestamp] = {
                        "name": "eamon",
                        "message": this.state.message,
                        "timestamp": timestamp,
                        "dates": JSON.stringify(this.state.datesArray)
                      };
    
                      this.sendRentMessage(dataChat, dataMessage, timestamp)
                      this.setModalVisible(false)
                    }, 1)
                  }}>
                  <Text
                    style={{
                      backgroundColor: this.state.rentButtonBackground,
                      textAlign: 'center',
                      color: 'white',
                      fontWeight: '900',
                      fontSize: 18,
                      borderRadius: 4,
                      borderWidth: 0,
                    }}>
                    SEND
                  </Text>
                </TouchableOpacity>
              </View>
            </View>
          </View>
        </TouchableWithoutFeedback>
      );
    
      componentDidMount() {
        firebase.messaging()
          .hasPermission()
          .then(enabled => {
            if (!enabled) {
              console.log('permissions disabled');
              this._getPermission();
            }
    
            console.log('permissions enabled');
    
            firebase.messaging().subscribeToTopic('all').catch((error) => {alert(error)});
    
            firebase.messaging().getToken()
              .then(fcmToken => {
                if (fcmToken) {
                  //USE THIS FOR INDIVIDUAL DEVICE MESSAGES?
                  console.log(fcmToken);
                } else {
                  alert("User doesn't have a token yet");
                } 
    
              }).catch((error) => {
                alert(error);
              });
    
          }).then(() => {
    
          }).catch((error) => {alert(error)});
      }
    
      _getPermission = () => {
        firebase.messaging()
          .requestPermission()
          .catch(error => {
            // User has rejected permissions
            // this._getPermission();
            Alert.alert(
              'ERROR',
              "You must enable push notifications for the messaging system to work! If you don't you won't be able to use SnagIt! Please enable notificaitons in your phone - go to: Settings > Notifications > SnagIt.",
              [
                {text: 'OK', onPress: () => console.log('OK Pressed')},
              ],
              { cancelable: false }
            )
          });
      }
    
      sendRentMessage(dataChat, dataMessage, timestamp) {
    
        // Add a new document with a generated id.                          //user-user                           //send generated ID and then change to message id in cloud
        /*let addChat = firebase.firestore().collection('chats').doc(timestamp);
        // Add a new document with a generated id.                          //user-user                           //send generated ID and then change to message id in cloud
        let addMessage = firebase.firestore().collection('messages').doc(timestamp);
    
        // Set the 'capital' field of the city
        addChat.update(dataChat).then(() => {
                        // Set the 'capital' field of the city
          addMessage.update(dataMessage).catch((error) => {
            //alert(error);
            addMessage.set(dataMessage).catch((error) => {
              alert(error);
            });
          });
        }).catch((error) => {
          //alert(error);
          addChat.set(dataChat).catch((error) => {
            alert(error);
          }).then(() => {
            addMessage.update(dataMessage).catch((error) => {
              //alert(error);
              addMessage.set(dataMessage).catch((error) => {
                alert(error);
              });
            });
          })
        });*/
      }
    
      render() {
        return (
          <View style={{flex: 1}}>
            <Modal
              animationType="slide"
              transparent={true}
              visible={this.state.modalVisible}
              onBackdropPress ={() => {console.log("backdrop pressed"); this.setModalVisible(false)}}>
              {this._renderModalContent()}
            </Modal>
          </View>
        )
      }
    }
    

    对于控制台输出,我看到:

    this.state.showRespondTo: – true

    所以我知道条件正在变为它应该呈现组件的状态。我也看到一半的屏幕(组件应该在哪里)是空白/白色背景。这是因为我的 flexbox 设置,是我想要的行为。但是应该呈现的元素没有出现。条件变化的状态 didFocus

    componentDidMount() {
    
        this._sub = this.props.navigation.addListener(
          'didFocus',
          () => {
            if(this.props.navigation.getParam('data', '') != '') {
              console.log('showRespondTo fired.');
              this.setState({showRespondTo: true});
            }
          }
        );
    
        ....
    
    }
    

    为什么我的 InitiateRent 空白/白色区域的组件渲染(参见下面的图像)?

    enter image description here

    1 回复  |  直到 6 年前
        1
  •  0
  •   ewizard    6 年前

    只是一些傻事, this.state.modalVisible