React-Native:getCurrentLocation = null的setState()

时间:2018-04-12 18:32:47

标签: firebase react-native location state-management

我希望得到我的任务的距离,这是具有lat lng值的对象。它们保存在我的firebase数据库中。

现在我的问题是,我通过setState在componentWillMount中设置用户的当前位置。但是当我从异步任务(firebase查询)调用getDistance时,用户当前位置的状态为null。

我认为这是因为操作不在同一个上下文中。所以我试着深入研究redux,但却无法掌握这个话题。

我怎么解决这个问题?

      getDistance(latitude, longitude) {
        let c = geolib.getDistance(
          { latitude: { latitude }, longitude: { longitude } }, // strawa
          { latitude: this.state.latitude, longitude: this.state.longitude }, // sbg
          100,
          1
        );
        return c / 1000;
        //alert(c / 1000); // 25km
      }

      /*
          Get the Users current location
          iOS -> asks only one time for permission, so pay atention if disabled !!!
      */
      getCurrentLocation() {
        var loc;
        navigator.geolocation.getCurrentPosition(
          position => {
            console.log("Location Request - Position = " + position);
            this.setState({
              latitude: position.coords.latitude,
              longitude: position.coords.longitude
            });
          },
          error => this.setState({ error: error.message }),
          { enableHighAccuracy: false, timeout: 200000, maximumAge: 1000 }
        );
      }

      componentWillMount() {
        //this.getCurrentLocation();
        this.listenForTasks(this.tasksRef);
      }

  listenForTasks(tasksRef) {
    tasksRef.on("value", snap => {
      var tasks = [];
      snap.forEach(child => {
        // If Task_Type = 0 getDistance
        var distance = "";
        if (child.val().type === "0") {
          distance = this.getDistance(child.val().lat, child.val().lng);
        } else {
          distance = "Online";
        }
        tasks.push({
          title: child.val().title,
          budget: child.val().budget,
          offersCount: child.val().offersCount,
          commentsCount: child.val().commentsCount,
          distance: distance
        });
      });
      tasks.reverse();
      this.setState({
        dataSource: this.state.dataSource.cloneWithRows(tasks)
      });
    });
  }

这是我尝试以非常简单的方式实现redux的不好尝试,但是我收到了一个错误:"预期的监听器是一个函数"

import { createStore } from "redux";

const reducer = (state = [], action) => {
  if (action.type === "getCurrentLocation") {
    return action.payload;
  }
  return state;
};
const store = createStore(reducer);

class TaskBrowseScreen extends React.Component {
  constructor(props) {
    super(props);

    store.dispatch({ type: "getCurrentLocation", payload: "?" });
    store.subscribe();
...

1 个答案:

答案 0 :(得分:-1)

首先,您不应该在componentWillMount =>中执行此操作。 why? manual

您的问题出现是因为您没有连结来电。最好在设置getDistance的位置后调用geolocation

最简单的方法是返回一个承诺:

constructor() {
  super();

  this.getCurrentLocation().then(() => {
    this.listenForTasks();
  });
}

getCurrentLocation() {
  let resolver;
  let rejector;
  const promise = new Promise((resolve, reject) => {
    resolver = resolve;
    rejector = reject;
  });
  var loc;
  navigator.geolocation.getCurrentPosition(
    position => {
      console.log("Location Request - Position = " + position);
      this.setState({
        latitude: position.coords.latitude,
        longitude: position.coords.longitude
      }, resolver);
    },
    error => this.setState({ error: error.message }, rejector),
    { enableHighAccuracy: false, timeout: 200000, maximumAge: 1000 }
  );

  return promise;
}

UPD: 它对你来说可能很重要,不要花时间将所有异步方法一个接一个地链接到期望中。在你致电getDistance之前,你可以存储承诺并建立一个链:

constructor() {
  super();

  this._promise = this.getCurrentLocation();
  this.listenForTasks();
}

listenForTasks() {
  // some async
    this._promise.then(() => {
      this.getDistance();
    });
}

您可能不会花时间并且并行调用db.call。