位置跟踪反应组件 - 如何处理侦听器/更新

时间:2016-02-03 02:08:43

标签: design-patterns reactjs geolocation

我有一个"哑巴"显示大约的组件。两个地点之间的距离。

import React from "react"

const cos = Math.cos
const p = Math.PI / 180
function getDistance(lat1, lon1, lat2, lon2) {
  var a = 0.5 - c((lat2 - lat1) * p)/2 +
          c(lat1 * p) * c(lat2 * p) *
          (1 - c((lon2 - lon1) * p))/2
  return 12742 * Math.asin(Math.sqrt(a)) // 2 * R; R = 6371 km
}

let Distance = ({from,to}) => {
    let distance = getDistance(
      from.latitude,
      from.longitude,
      to.latitude,
      to.longitude)
    if (distance < 1.0) {
      distance = (distance * 100) + "m"
    } else {
      distance = distance + "km"
    }
    return <span>{distance}</span>
  }
}
Distance.displayName = "Distance"

我想通过在浏览器地理位置发生变化时更新组件来增强此组件。所以我创建了另一个组件

class TrackingDistance extends React.Component {
  constructor(props) {
    super(props)
    this.updatePosition = this.updatePosition.bind(this)
    if (TrackingDistance.lastPosition) {
      this.updatePosition(TrackingDistance.lastPosition)
    } else {
      navigator.geolocation.getCurrentPosition(this.updatePosition)
    }
  }

  updatePosition(position) {
    this.setState({from: position.coords})
  }

  componentDidMount() {
    if (TrackingDistance.instances.length === 0) {
      TrackingDistance.watchId = navigator.geolocation.watchPosition(position => {
        TrackingDistance.instances.map(instance => instance.updatePosition(position))
      })
    }
    TrackingDistance.instances.push(this)
  }

  componentWillUnmount() {
    TrackingDistance.instances.remove(this)
    if (TrackingDistance.instances.length === 0) {
      navigator.geolocation.clearWatch(TrackingDistance.watchId)
    }
  }

  render() {
    return this.state.from ? <Distance to={this.props.to} from={this.state.from}/> : null
  }
}
TrackingDistance.instances = []
TrackingDistance.watchId = 0
TrackingDistance.lastPosition = null

我的目标是在我的应用中只为地理位置更新注册一次事件监听器,而不是每个组件都有一个监听器。我担心在将组件实例保存在静态数组TrackingDistance.instances中时会创建循环引用。

也允许从组件本身外部调用其他组件的setState方法(就像我在我的位置监听器中那样?)

还有其他反应模式可以更好地解决这个问题吗?我无法使用Mixins,因为我使用的是ES6 React组件类。

0 个答案:

没有答案