Code Monkey home page Code Monkey logo

Comments (3)

gtwilliams03 avatar gtwilliams03 commented on June 13, 2024

Never mind. I didn't read far enough. :)

By default the component only sets position once. To watch the user's position and provide live updates to position, set watchPosition = true. The geolocation event handler is unregistered when the component unmounts.

from react-geolocated.

rosman21 avatar rosman21 commented on June 13, 2024

How did you go about watching the position in your application? Having a hard time trying to get it to work

from react-geolocated.

gtwilliams03 avatar gtwilliams03 commented on June 13, 2024

@rosman21 Sorry for the delay! Wasn't paying attention to this. Here is what I ended up doing. I created a GeolocationUpdater component which I dropped into any view that I wanted to track the user's location. This sets a state variable to watch for any location changes every 60 seconds (this is a mobile app so I didn't want to look any more frequently and kill the user's battery):

GeolocationUpdater component:

import React, { Component } from 'react'
import PropTypes from 'prop-types'
import { connect } from 'react-redux'
import { geolocated } from 'react-geolocated'
import { geoLocationSuccess, geoLocationError, updateGeoLocationSettings, postUserGeolocation } from './modules/geoLocation'
import { JSON_DATE_FORMAT } from '../../constants/appConstants'
import moment from 'moment'

class GeolocationUpdater extends Component {

    static propTypes = {
        show: PropTypes.bool,
    }

    static defaultProps = {
        show: false,
    }

    constructor(props) {
        super(props)
        this.state = { isSaving: false, saveIntervalSeconds: 60 }
    }

    componentWillMount() {
        this.updateLocationCheck(this.props)
    }

    componentWillReceiveProps(nextProps) {
        this.updateLocationCheck(nextProps)
    }

    updateLocationCheck(props) {
        const { isGeolocationAvailable, isGeolocationEnabled, geoLocationLocalState, postUserGeolocation, updateGeoLocationSettings } = props
        const { isSaving, saveIntervalSeconds } = this.state
        if (isGeolocationAvailable !== this.props.isGeolocationAvailable || isGeolocationEnabled !== this.props.isGeolocationEnabled) {
            updateGeoLocationSettings({ isGeolocationAvailable, isGeolocationEnabled })
        }
        if (isGeolocationAvailable && isGeolocationEnabled) {
            if (isGeolocationAvailable && isGeolocationEnabled) {
                const lastUpdate = moment(geoLocationLocalState.lastUpdate, JSON_DATE_FORMAT)
                const lastServerUpdate = moment(geoLocationLocalState.lastServerUpdate, JSON_DATE_FORMAT)
                const elapsedTime = lastUpdate.diff(lastServerUpdate, 'seconds')

                const savePosition = { coords: { ...geoLocationLocalState, secondsSinceLastUpdate: elapsedTime } }
                if (elapsedTime > saveIntervalSeconds && !isSaving && geoLocationLocalState.latitude != 0.0000 && geoLocationLocalState.longitude !== 0.0000) {
                    this.setState({ isSaving: true }, () => {
                        postUserGeolocation(savePosition)
                        .then(() => this.setState({ isSaving: false }))
                    })
                } else if (elapsedTime !== geoLocationLocalState.secondsSinceLastUpdate) {
                    updateGeoLocationSettings({ isGeolocationAvailable, isGeolocationEnabled, secondsSinceLastUpdate: elapsedTime })
                }
            }
        }
    }

    render() {
        const { show, geoLocationLocalState } = this.props
        return (
            <div>
                {show ? <pre style={{ whiteSpace: 'normal' }}>{JSON.stringify(geoLocationLocalState)}</pre> : null}
            </div>
        )
    }

}

const mapDispatchToProps = (dispatch, ownProps) => ({
    onSuccess: position => dispatch(geoLocationSuccess(position)),
    onError: error => dispatch(geoLocationError(error)),
    updateGeoLocationSettings: (isGeolocationAvailable, isGeolocationEnabled) => dispatch(updateGeoLocationSettings(isGeolocationAvailable, isGeolocationEnabled)),
    postUserGeolocation: position => dispatch(postUserGeolocation(position)),
})

const mapStateToProps = (state, ownProps) => ({
    show: ownProps.show,
    geoLocationLocalState: { ...state.geoLocation },
    isAuthenticated: state.account.isAuthenticated,
})

export default connect(mapStateToProps, mapDispatchToProps)(geolocated({ 
    positionOptions: {
        enableHighAccuracy: true,
        maximumAge: 0,
        timeout: Infinity,
    },
    watchPosition: true,
    userDecisionTimeout: 5000,
    suppressLocationOnMount: false,
})(GeolocationUpdater))

geolocation.js reducer

import { CALL_API } from 'redux-api-middleware'
import { API_URL, INITIAL_STATE, JSON_DATE_FORMAT } from '../../../constants/appConstants'
import { reject, merge } from 'lodash'
import moment from 'moment'

/* Action Types */
export const GEOLOCATION_UPDATE = '@@geoLocation/GEOLOCATION_UPDATE'
export const GEOLOCATION_UPDATE_SETTINGS = '@@geoLocation/GEOLOCATION_UPDATE_SETTINGS'

export const GEOLOCATION_UPDATE_START = '@@geoLocation/GEOLOCATION_UPDATE_START'
export const GEOLOCATION_UPDATE_COMPLETE = '@@geoLocation/GEOLOCATION_UPDATE_COMPLETE'
export const GEOLOCATION_UPDATE_ERROR = '@@geoLocation/GEOLOCATION_UPDATE_ERROR'
export const GEOLOCATION_UPDATE_POST_ERROR = '@@geoLocation/GEOLOCATION_UPDATE_POST_ERROR'

export const GEOLOCATION_UPDATE_SUCCESS = '@@geoLocation/GEOLOCATION_UPDATE_SUCCESS'

export const GEOLOCATION_SEND_START = '@@geoLocation/GEOLOCATION_SEND_START'
export const GEOLOCATION_SEND_COMPLETE = '@@geoLocation/GEOLOCATION_SEND_COMPLETE'
export const GEOLOCATION_SEND_ERROR = '@@geoLocation/GEOLOCATION_SEND_ERROR'

/* Actions */
export function geoLocationConverter(position) {
    var data = {
        error: {},
        ...(position.coords.latitude && { latitude: position.coords.latitude }),
        ...(position.coords.longitude && { longitude: position.coords.longitude }),
        ...(position.coords.accuracy && { accuracy: position.coords.accuracy }),
        ...(position.coords.altitude && { altitude: position.coords.altitude }),
        ...(position.coords.altitudeAccuracy && { altitudeAccuracy: position.coords.altitudeAccuracy }),
        ...(position.coords.heading && { heading: position.coords.heading }),
        ...(position.coords.speed && { speed: position.coords.speed }),
        ...(position.coords.secondsSinceLastUpdate && { secondsSinceLastUpdate: position.coords.secondsSinceLastUpdate }),
        lastUpdate: moment.unix(position.timestamp / 1000.0).format(JSON_DATE_FORMAT),
    }
    return data
}

export function geoLocationSuccess(position) {
    return { type: GEOLOCATION_UPDATE_SUCCESS, payload: geoLocationConverter(position) }
}

export function postUserGeolocation(position) {
    return {
        [CALL_API]: {
            endpoint: API_URL + 'UpdateUserGeolocation',
            method: 'POST',
            body: JSON.stringify(geoLocationConverter(position)),
            types: [GEOLOCATION_UPDATE_START, GEOLOCATION_UPDATE_COMPLETE, GEOLOCATION_UPDATE_POST_ERROR]
        }
    }
}

export function geoLocationError(error) {
    console.log("geoLocation error", error)
    return { type: GEOLOCATION_UPDATE, payload: error }
}

export function updateGeoLocationSettings(o) {
    return { type: GEOLOCATION_UPDATE_SETTINGS, payload: o }
}

/* Action Handlers */
const ACTION_HANDLERS = {
    [GEOLOCATION_UPDATE]: (state, action) => { return { ...state, ...action.payload, } },

    [GEOLOCATION_UPDATE_ERROR]: (state, action) => { return { ...state, error: { ...action.payload } } },

    [GEOLOCATION_UPDATE_START]: (state, action) => { return { ...state, isFetching: true } },
    [GEOLOCATION_UPDATE_COMPLETE]: (state, action) => { return { ...state, lastServerUpdate: moment().format(JSON_DATE_FORMAT), serverIsUpdated: true, isFetching: false } },

    [GEOLOCATION_UPDATE_POST_ERROR]: (state, action) => { return { ...state, isFetching: false } },

    [GEOLOCATION_UPDATE_SUCCESS]: (state, action) => { return { ...state, ...action.payload } },
    
    [GEOLOCATION_UPDATE_SETTINGS]: (state, action) => { return { ...state, ...action.payload } },

}

/* Reducer */
export default function geoLocationReducer(state = INITIAL_STATE.geoLocation, action) {
    const handler = ACTION_HANDLERS[action.type]
    return handler ? handler(state, action) : state
}

INITIAL_STATE.geolocation:

    geoLocation: {
        latitude: 0.00000,
        longitude: 0.00000,
        accuracy: 0,
        altitude: 0.00000,
        altitudeAccuracy: 0.00000,
        heading: 0,
        speed: 0,
        error: {},
        isGeolocationAvailable: false, 
        isGeolocationEnabled: false,
        lastUpdate: moment().subtract(1, 'hour').format(JSON_DATE_FORMAT),
        lastServerUpdate: moment().subtract(1, 'hour').format(JSON_DATE_FORMAT),
        secondsSinceLastUpdate: 0,
    },

from react-geolocated.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.