首页 > 解决方案 > 在 Android 上强制退出并重新打开应用程序后,组件上的引用为空

问题描述

我有一个使用react-native-maps的反应原生应用程序的代码。我试图通过在 Marker 组件上创建 ref 来使用 Marker 组件的 showCallout 方法在应用程序启动时立即打开 Marker 的 Callout 组件。这是代码:

import React, { Component } from "react";
import { Platform, StyleSheet, Text, View } from "react-native";
import MapView, { PROVIDER_GOOGLE, Marker, Callout } from "react-native-maps";
import { PermissionsAndroid } from "react-native";
import { apiKey } from "./apiKey";
import CustomCallout from "./CustomCallout";

export default class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      latitude: null,
      longitude: null,
      error: null,
      locationGranted: null,
      currentWeather: "Loading weather data..."
    };
    this.requestLocationPermission = this.requestLocationPermission.bind(this);
    this.getWeather = this.getWeather.bind(this);
    this.setMarkerRefresh = this.setMarkerRefresh.bind(this);
  }

  componentDidMount() {
    this.requestLocationPermission();
  }

  async getWeather(lat, long) {
    try {
      let response = await fetch(
        `https://api.darksky.net/forecast/${apiKey}/${lat},${long}`
      );
      let responseJson = await response.json();
      let thisHour = responseJson.hourly.data[0];
      this.setState(
        {
          currentWeather: `${thisHour.temperature} ${thisHour.windSpeed} ${
            thisHour.summary
          }`
        },
        this.setMarkerRefresh
      );
    } catch (error) {
      console.error(error);
    }
  }

  setMarkerRefresh() {
    setTimeout(this.currentMarker.showCallout, 1);
  }

  async requestLocationPermission() {
    try {
      const granted = await PermissionsAndroid.request(
        PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,
        {
          title: "Location Permission",
          message:
            "This app needs access to your location to provide you location data.",
          buttonPositive: "OK"
        }
      );
      if (granted === PermissionsAndroid.RESULTS.GRANTED) {
        navigator.geolocation.getCurrentPosition(
          position => {
            this.setState({
              latitude: position.coords.latitude,
              longitude: position.coords.longitude,
              error: null,
              locationGranted: true
            });
            this.getWeather(
              position.coords.latitude,
              position.coords.longitude
            );
          },
          error => this.setState({ error: error.message }),
          { enableHighAccuracy: true, timeout: 200000, maximumAge: 1000 }
        );
      } else {
        this.setState({ locationGranted: false });
      }
    } catch (err) {
      console.warn(err);
    }
  }

  render() {
    if (this.state.locationGranted === false) {
      return (
        <View>
          <Text> Please enable location to use this app. </Text>
        </View>
      );
    } else if (this.state.latitude === null || this.state.longitude === null) {
      return (
        <View>
          <Text> {this.state.error} </Text>
        </View>
      );
    } else {
      return (
        <View style={styles.container}>
          <MapView
            provider={PROVIDER_GOOGLE} // remove if not using Google Maps
            style={styles.map}
            region={{
              latitude: this.state.latitude,
              longitude: this.state.longitude,
              latitudeDelta: 0.025,
              longitudeDelta: 0.025
            }}
          >
            <Marker
              coordinate={{
                latitude: this.state.latitude,
                longitude: this.state.longitude
              }}
              ref={ref => {
                this.currentMarker = ref;
              }}
            >
              <Callout tooltip={true}>
                <CustomCallout>
                  <Text style={{ color: "white", textAlign: "center" }}>
                    {this.state.currentWeather}
                  </Text>
                </CustomCallout>
              </Callout>
            </Marker>
          </MapView>
        </View>
      );
    }
  }
}

const styles = StyleSheet.create({
  container: {
    ...StyleSheet.absoluteFill,
    justifyContent: "flex-end",
    alignItems: "center"
  },
  map: {
    ...StyleSheet.absoluteFillObject
  },
  customView: {
    width: 140,
    height: 140
  }
});

该代码在应用程序的初始打开时按预期工作。但是,当我强制退出应用程序并尝试重新打开它时,我收到此错误:

TypeError: null is not an object (evaluating 'currentMarker.showCallout')

This error is located at:
    in App (at renderApplication.js:35)
    in RCTView (at View.js:45)
    in View (at AppContainer.js:98)
    in RCTView (at View.js:45)
    in View (at AppContainer.js:115)
    in AppContainer (at renderApplication.js:34)
setMarkerRefresh

我不确定在导致此错误的组件安装/卸载方面发生了什么。我曾尝试在网上搜索,但没有取得太大的成功。谁能帮帮我?谢谢!

标签: reactjsreact-native

解决方案


你能改变你的方法,setMarkerRefresh

setMarkerRefresh() {
    // setTimeout(this.currentMarker.showCallout, 1);
    setTimeout(() => {
      this.currentMarker.showCallout;
    }, 1000);
  }

推荐阅读