Как я могу отменить все подписки и асинхронные задачи после первого OnPress на TouchableOpacity? - PullRequest
0 голосов
/ 13 февраля 2019

Фоновый процесс не отменяется, когда я нажимаю кнопку (Bluetooth -> выключен), чтобы сканировать близлежащие устройства Bluetooth.

Библиотеки иИспользуемые языки: реакции-нативный, реагировать-нативный-ble-plx, / реагировать-нативный-bluetooth-state-manager

Я довольно новичок в реакции-нативный и в программировании в целом.В настоящее время я занимаюсь разработкой приложения, которое использует некоторые библиотеки для управления и сканирования устройств Bluetooth.

Функциональность сканирования ближайших устройств Bluetooth может быть выполнена только при включенном Bluetooth.

ЕслиBluetooth не включен, пользователь все еще может нажать кнопку (touchableopacity) и получить уведомление о том, что он должен активировать Bluetooth.

В этот момент пользователь активирует Bluetooth, а затем, в некоторых случаях,приложение начинает обнаруживать устройства Bluetooth.Это реальная проблема.

Я хотел бы отменить первый OnPress, который остается в фоновом режиме?и заставьте пользователя нажать кнопку еще раз для сканирования устройств.

Когда появляется эта «ошибка», я получаю это предупреждение через React Native Debugger.

Предупреждение: Невозможно выполнить обновление состояния React для отключенного компонента.Это не работает, но это указывает на утечку памяти в вашем приложении.Чтобы исправить, отмените все подписки и асинхронные задачи в методе componentWillUnmount

Примечание: я должен смешать оба компонента componentWillUnmount ()?

Я застрял с этим на день, я бы действительноценю любую помощь.Заранее спасибо.

        import React, { Component } from 'react';
    import { NavigationActions, StackActions } from "react-navigation";
    import {
    Platform,
    Text,
    View,
    Alert,
    Button,
    TouchableOpacity,
    ActivityIndicator,
    StyleSheet
    } from 'react-native';
    import {Agenda} from 'react-native-calendars';
    import { BleManager, Device, BleError, LogLevel } from "react-native-ble-plx";
    import axios from 'axios';
    import {LocaleConfig} from 'react-native-calendars';
    import SInfo from "react-native-sensitive-info";
    import Icon from "react-native-vector-icons/Ionicons";
    import BottomToolbar from 'react-native-bottom-toolbar';
    import { BluetoothStatus } from 'react-native-bluetooth-status';
    import Spinner from 'react-native-loading-spinner-overlay';
    import BluetoothStateManager from 'react-native-bluetooth-state-manager';

    LocaleConfig.locales['es'] = {
    monthNames: ['Enero','Febrero','Marzo','Abril','Mayo','Junio','Julio','Agosto','Septiembre','Octubre','Noviembre','Diciembre'],
    monthNamesShort: ['Ene.','Febr.','Mar.','Abr.','May.','Jun.','Jul.','Ago.','Sept.','Oct.','Nov.','Dic.'],
    dayNames: ['Domingo','Lunes','Martes','Miercoles','Jueves','Viernes','Sabádo'],
    dayNamesShort: ['Dom.','Lun.','Mar.','Mie.','Jue.','Vie.','Sáb.']
    };

    LocaleConfig.defaultLocale = 'es';


    type Props = {};

    type State = {
    text: Array<string>
    };



    export default class Calendar extends Component {
    static navigationOptions = ({ navigation }) => {
      return {
        title: /* navigation.getParam('user', '') + ' | */'Calendario de ponencias',
        headerRight: (
          <TouchableOpacity onPress={() => null}>
            <View style={styles.buttonInfo}>
              <Text style={styles.text}>INFO</Text>
            </View>
          </TouchableOpacity>
      ),headerLeft: null
      };
    };
    _isMounted = false;
    constructor(props) {
      super(props);
      this.state = {
        items: {},
        bluetoothState: null,
        requesting: null,
        ponencias: [],
        counter: false,
        btStatus: false,
        ver: false,
        spinner: false,
        isLoading: true,
        actualDay: '',
        buttonColor: 'red' // default button color goes here
      };
    }

    async componentDidMount(){
      //this.checkInitialBluetoothState();
      this.bluetoothStateChangeSubscription = await BluetoothStateManager.onStateChange(
        this.onBluetoothStateChange,
        true /*=emitCurrentState*/
      );
      this.setState({ isLoading: true });
      this.loadPresentations();
    }

    componentWillUnmount() {
      if (this.bluetoothStateChangeSubscription) {
        this.bluetoothStateChangeSubscription.remove();
      }
    }

    onBluetoothStateChange = bluetoothState => {
      this.setState({ bluetoothState });
      console.log(this.state.bluetoothState);
    };


    loadPresentations(){
      SInfo.getItem('idToken',{}).then(idToken => {
        console.log("idTOKEN4 " + idToken);
            axios.get(`http://**.**.183.***:8080/api/lessons/` + idToken)
            .then(response => {
              console.log(response.data);
              this.setState({ponencias: response.data})
              this.setState({isLoading: false });
            })
        });
    }


    render() {
      if (this.state.isLoading) {
              return null;
      }

      const { navigation } = this.props;
      return (
      <View style={styles.container2}>
        <Spinner
            visible={this.state.ver}
            textContent={'Confirmando asistencia...'}
            textStyle={styles.spinnerTextStyle}
          />
        <Agenda
          items={this.state.items}
          loadItemsForMonth={this.loadItems.bind(this)}
          onDayPress={(day)=>{console.log('day pressed')}}
          onDayChange={(day)=>{console.log('day changed')}}
          selected={this.state.actualDay}
          renderItem={this.renderItem.bind(this)}
          renderEmptyDate={this.renderEmptyDate.bind(this)}
          rowHasChanged={this.rowHasChanged.bind(this)}
          theme={{calendarBackground: 'white', agendaKnobColor: 'grey'}}
          />
      </View>
        );
      }

      loadItems(day) {
        const myObj = {
          "ponencias": this.state.ponencias
        };
        setTimeout(() => {

          for (let i = -15; i < 80; i++) {
            const time = day.timestamp + i * 24 * 60 * 60 * 1000;
            const strTime = this.timeToString(time);
            if (!this.state.items[strTime]) {
              this.state.items[strTime] = [];
              let self = this;
              myObj.ponencias.forEach(function(item,index){
                if (strTime === item.day.date.substring(0, 10)) {
                  self.state.items[item.day.date.substring(0, 10)].push({
                    name: 'Ponencia ' + item.subject,
                    id: item.id,
                    height: Math.max(50, Math.floor(Math.random() * 150)),
                    date: item.day.date.substring(0, 10),
                    attendance: item.attendance,
                  });
                }
              });
            }
          }
          const newItems = {};
          Object.keys(this.state.items).forEach(key => {newItems[key] = this.state.items[key];});
          this._isMounted = true;
          if (this._isMounted) {
            this.setState({
              items: newItems
            });
          }
        }, 1000);
      }

      renderItem(item) {

        const manager = new BleManager();


        return (
          <View style={[styles.item, { width: "100%", backgroundColor: "white" }]}>
            <TouchableOpacity onPress={()=> {this.presentation(item.id);}}><Text style={{color: "black", textDecorationLine: 'underline', marginLeft: 6, fontSize: Platform.OS === 'ios' ? 12 : 12}}>{item.name}</Text></TouchableOpacity>

            <TouchableOpacity onPress={() => {

              if(this.state.bluetoothState === 'PoweredOn'){
                this.setState({counter: false})
              }

              if(this.state.bluetoothState === 'PoweredOff'){
                manager.stopDeviceScan();
                Alert.alert(
                  'Bluetooth desactivado',
                  'Debe activar el bluetooth para confirmar su asistencia a la ponencia.',
                  [
                    //{text: 'Ask me later', onPress: () => console.log('Ask me later pressed')},
                    //{text: 'Cancel', onPress: () => console.log('Cancel Pressed'), style: 'cancel'},
                    {text: 'OK', onPress: () => console.log('OK Pressed')},
                  ],
                  { cancelable: false }
                )
                return null;
              }

              if (this.state.counter) {
                return null;
              }
              if (item.attendance === true) {
                Alert.alert(
                  'Asistencia previamente confirmada',
                  'Su asistencia a la ponencia ya había sido confirmada con anterioridad.',
                  [
                    //{text: 'Ask me later', onPress: () => console.log('Ask me later pressed')},
                    //{text: 'Cancel', onPress: () => console.log('Cancel Pressed'), style: 'cancel'},
                    {text: 'OK', onPress: () => console.log('OK Pressed')},
                  ],
                  { cancelable: false }
                )
                return null;
              }
                if(this.state.bluetoothState === 'PoweredOff'){
                    this.setState({counter: true})
                    Alert.alert(
                      'Bluetooth desactivado',
                      'Debe activar el bluetooth para confirmar su asistencia a la ponencia.',
                      [
                        //{text: 'Ask me later', onPress: () => console.log('Ask me later pressed')},
                        //{text: 'Cancel', onPress: () => console.log('Cancel Pressed'), style: 'cancel'},
                        {text: 'OK', onPress: () => console.log('OK Pressed')},
                      ],
                      { cancelable: false }
                    )
                    return null;
                }else if(this.state.bluetoothState === 'PoweredOn'){
                  if (this.checkDay(item)) {
                    if(item.attendance !== true){
                      console.log("entra");
                      this.setState({ ver: true });
                      var beacon1_detect = false;
                      var beacon2_detect = false;
                      var beacon3_detect = false;

                      var beacon1_detect_ios = false;
                      var beacon2_detect_ios = false;
                      var beacon3_detect_ios = false;

                      //this.setState({ ver: true });
                     if(this.state.bluetoothState === 'PoweredOff'){
                       manager.stopDeviceScan();
                     }else{
                     manager.onStateChange(newState => {
                        if (newState != "PoweredOn") return;
                        if(this.state.counter === false){
                        manager.startDeviceScan(
                          null,
                          {
                            allowDuplicates: false
                          },
                          (error, device) => {
                            if (error) {
                              return;
                            }
                            //this._log("Device: " + device.id, device);
                            if (device.id == 'D7:E7:89:5A:7A:49' || device.id == '47E488CF-1160-5FB6-E429-C3DEE737538E'){
                              beacon1_detect = true;
                              beacon1_detect_ios = true;

                            }
                            if (device.id == 'C9:6A:6E:07:6D:72' || device.id == '5D6D2889-ED22-940B-236C-EA882A2346D3'){
                              beacon2_detect = true;
                              beacon2_detect_ios = true;

                            }
                            if (device.id == 'D2:2B:25:30:D7:F8' || device.id == '32DD3745-C65A-850A-97FF-DA593FCDA2BB'){
                              beacon3_detect = true;
                              beacon3_detect_ios = true;
                            }

                            if((beacon1_detect && beacon2_detect && beacon3_detect) || beacon1_detect_ios && beacon2_detect_ios && beacon3_detect_ios){
                              // Ingresar que el alumno 'a' en cuestión ha asistido a la ponencia 'x' a la hora 'h'
                              this.registerAttendance(item);
                              item.attendance = true;
                              this.setState({ ver: false });
                              console.log("Alumno en clase");
                              manager.stopDeviceScan()
                              Alert.alert(
                                'Asistencia confirmada',
                                'Se ha confirmado tu asistencia a la ponencia.',
                                [
                                  //{text: 'Ask me later', onPress: () => console.log('Ask me later pressed')},
                                  //{text: 'Cancel', onPress: () => console.log('Cancel Pressed'), style: 'cancel'},
                                  {text: 'OK', onPress: () => console.log('OK Pressed')},
                                ],
                                { cancelable: false }
                              )

                            }else{
                              console.log("Alumno no en clase. Detectando beacons.");
                             }

                              console.log("DEVICE " + device.name + " WITH MAC = " + device.id);
                              console.log("DEVICE " + device.name + " POWER = " + device.rssi + "dB");
                              //manager.stopDeviceScan()
                            }
                        );
                       }
                      }, true);
                     }
                    }
                  }else if(!this.checkDay(item)) {
                    Alert.alert(
                      'Asistencia no confirmada',
                      'Sólo puede confirmar la asistencia en el día correspondiente a la ponencia.',
                      [
                        //{text: 'Ask me later', onPress: () => console.log('Ask me later pressed')},
                        //{text: 'Cancel', onPress: () => console.log('Cancel Pressed'), style: 'cancel'},
                        {text: 'OK', onPress: () => console.log('OK Pressed')},
                      ],
                      { cancelable: false }
                    )
                  }
                }

            }}>
              <View style={this.checkDay(item) ? styles.button : styles.buttonNo}>
                <Text style={styles.text}>Confirmar asistencia</Text>
              </View>
            </TouchableOpacity>

            <TouchableOpacity onPress={()=> {
              if (item.attendance) {
                this.poll(item.id);
              }else{
                Alert.alert(
                   'Asistencia no confirmada.',
                   'Su asistencia a la ponencia debe ser confirmada antes de realizar la encuesta.',
                   [
                     //{text: 'Ask me later', onPress: () => console.log('Ask me later pressed')},
                     //{text: 'Cancel', onPress: () => console.log('Cancel Pressed'), style: 'cancel'},
                     {text: 'OK', onPress: () => console.log('OK Pressed')},
                   ],
                   { cancelable: false }
                 )
                return null;
              }
            }}>
              <View style={this.checkAttendance(item) ? styles.buttonPoll : styles.buttonPollNo}>
                <Text style={styles.text}>Realizar encuesta</Text>
              </View>
            </TouchableOpacity>
        </View>
      );
    }

    checkDay(item){
      console.log(item);
      var today = new Date();
      var month = parseInt(today.getMonth()+1);
      var hoy = today.getDate();
      if (hoy < 10) {
        hoy = '0' + hoy
      }
      if (month < 10) {
        month = '0' + month
      }

      date = today.getFullYear() + "-" + month + "-" + hoy;
      this.setState({ actualDay: date });
      if (item.date === date && item.attendance === false) {
        return true;
      }
      else{
        return false;
      }
    }

    checkAttendance (item){
      if (item.attendance == false) {
          return false;
      }
      else{
          return true;
      }
    }

    beacon = (item) => {


    };

    registerAttendance = (item) => {
      SInfo.getItem('idToken',{}).then(idToken => {
      console.log(idToken);
      console.log(item.id);
      axios.post('http://**.**.183.***:8080/api/attendance/' + item.id + '/' + idToken).then((response ) => {
           console.log(response);
           this.loadPresentations();
           this.forceUpdate();

        })
        .catch((error) => {
           console.log("axios error:",error);
        })
      });

    }

    poll = (idSurvey) => {
      const resetAction = StackActions.reset({
        index: 0,
        actions: [
          NavigationActions.navigate({
            routeName: "Poll",
            params: {
              idSurvey: idSurvey
            }
          })
        ]
      });
      this.props.navigation.dispatch(resetAction);
    };


    presentation = (idPresentation) => {
      const resetAction = StackActions.reset({
        index: 0,
        actions: [
          NavigationActions.navigate({
            routeName: "Presentation",
            params: {
              idPresentation: idPresentation
            }
          })
        ]
      });
      this.props.navigation.dispatch(resetAction);
    };


    renderEmptyDate() {
      return (
        <View style={styles.emptyDate}><Text>No hay ninguna ponencia</Text></View>
      );
    }

    rowHasChanged(r1, r2) {
      return r1.name !== r2.name;
    }

    timeToString(time) {
      const date = new Date(time);
      return date.toISOString().split('T')[0];
    }
    componentWillUnmount() {
       this._isMounted = false;
     }
    }

    const styles = StyleSheet.create({
    item: {
      backgroundColor: 'white',
      flex: 1,
      borderRadius: 5,
      padding: 20,
      alignItems: 'center',
      flexDirection: 'row',
      justifyContent: 'center',
      marginTop: 17
    },
    container2: {
      flex: 1,
      backgroundColor: '#F5FCFF'
    },
    emptyDate: {
      height: 15,
      marginRight: 10,
      flex:1,
      paddingTop: 30
    },
    button: {
       margin: 5,
       paddingHorizontal: 6,
       paddingVertical: 5,
       borderRadius: 5,
       backgroundColor: "red"
     },
     buttonNo: {
        margin: 5,
        paddingHorizontal: 6,
        paddingVertical: 5,
        borderRadius: 5,
        backgroundColor: "#ffb2b2"
      },
    buttonPoll: {
      marginRight: 20,
      paddingHorizontal: 6,
      paddingVertical: 5,
      borderRadius: 5,
      backgroundColor: Platform.OS === 'ios' ? "green" : "green"
    },
    buttonPollNo: {
      marginRight: 20,
      paddingHorizontal: 6,
      paddingVertical: 5,
      borderRadius: 5,
      backgroundColor: "#76a076"
    },
    spinnerTextStyle: {
       color: '#FFF'
     },
    buttonInfo: {
      margin: 5,
      paddingHorizontal: 8,
      paddingVertical: 7,
      backgroundColor: "blue"
    },
     text: {
       color: '#fff',
       fontWeight: "bold",
       fontSize: Platform.OS === 'ios' ? 10 : 10
     }
    });
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...