I'm trying to get my position on a map and it works fine on my computer in Google Chrome, but when simulating to android/iPhone nothing happens when using for example Custom Location on iPhone Simulator. Tried it on my actual iPhone as well without any luck.
All settings I can find for accepting location on simulator/real device is ON
GoogleMap.js
import React from 'react'
import GoogleMapReact from 'google-map-react'
import {usePosition} from "./usePosition";
const defaultProps = {
center: {
lat: 10.0000000,
lng: 12.0000000,
},
zoom: 18.7,
}
const MeOnMap = ({ text }) => <div className="me-on-map"><img src="static/walking.gif" width="30" /></div>
const GoogleMap = () => {
const { latitude, longitude} = usePosition();
return (
<div style={{ marginLeft: '-17px', height: '528px', width: '109%' }}>
<GoogleMapReact
bootstrapURLKeys={{ key: '*********' }}
defaultCenter={defaultProps.center}
defaultZoom={defaultProps.zoom}
yesIWantToUseGoogleMapApiInternals
options={{ scrollwheel: false, zoomControl: false, fullscreenControl: false, gestureHandling: 'none', styles: [{ stylers: [{ 'saturation': 100 }, { 'gamma': 0.5 }]}] }}
>
<MeOnMap
lat={latitude}
lng={longitude}
text={''}
/>
</GoogleMapReact>
</div>
)}
export default GoogleMap
geo.js
import React from 'react';
import {usePosition} from './usePosition';
export const UsePositions = () => {
const {latitude, longitude} = usePosition();
return (
<code>
My position,<br/>
latitude: {latitude}<br/>
longitude: {longitude}<br/>
</code>
);
};
usePosition.js
import {useState, useEffect} from 'react';
const defaultSettings = {
enableHighAccuracy: false,
timeout: Infinity,
maximumAge: 0,
};
export const usePosition = (watch = false, settings = defaultSettings) => {
const [position, setPosition] = useState({});
const [error, setError] = useState(null);
const onChange = ({coords, timestamp}) => {
setPosition({
latitude: coords.latitude,
longitude: coords.longitude,
accuracy: coords.accuracy,
speed: coords.speed,
timestamp,
});
};
const onError = (error) => {
setError(error.message);
};
useEffect(() => {
if (!navigator || !navigator.geolocation) {
setError('Geolocation is not supported');
return;
}
let watcher = null;
if (watch) {
watcher =
navigator.geolocation.watchPosition(onChange, onError, settings);
} else {
navigator.geolocation.getCurrentPosition(onChange, onError, settings);
}
return () => watcher && navigator.geolocation.clearWatch(watcher);
}, [
settings.enableHighAccuracy,
settings.timeout,
settings.maximumAge,
]);
return {...position, error};
};
Anyone's got any idea what could be wrong?
Thanks!!
Never mind, it had to do with location being blocked if not gathered from secure connection
Origin does not have permission to use Geolocation service -- even over HTTPS
solved it by running npm with --https
Related
Here is what I have for now:
import {
Alert,
Animated,
Easing,
Linking,
StyleSheet,
Text,
View,
} from "react-native";
import React, { useEffect, useState } from "react";
import * as Location from "expo-location";
import * as geolib from "geolib";
import { COLORS } from "../../assets/Colors/Colors";
export default function DateFinder() {
const [hasForegroundPermissions, setHasForegroundPermissions] =
useState(null);
const [userLocation, setUserLocation] = useState(null);
const [userHeading, setUserHeading] = useState(null);
const [angle, setAngle] = useState(0);
useEffect(() => {
const AccessLocation = async () => {
function appSettings() {
console.warn("Open settigs pressed");
if (Platform.OS === "ios") {
Linking.openURL("app-settings:");
} else RNAndroidOpenSettings.appDetailsSettings();
}
const appSettingsALert = () => {
Alert.alert(
"Allow Wassupp to Use your Location",
"Open your app settings to allow Wassupp to access your current position. Without it, you won't be able to use the love compass",
[
{
text: "Cancel",
onPress: () => console.warn("Cancel pressed"),
},
{ text: "Open settings", onPress: appSettings },
]
);
};
const foregroundPermissions =
await Location.requestForegroundPermissionsAsync();
if (
foregroundPermissions.canAskAgain == false ||
foregroundPermissions.status == "denied"
) {
appSettingsALert();
}
setHasForegroundPermissions(foregroundPermissions.status === "granted");
if (foregroundPermissions.status == "granted") {
const location = await Location.watchPositionAsync(
{
accuracy: Location.Accuracy.BestForNavigation,
activityType: Location.ActivityType.Fitness,
distanceInterval: 0,
},
(location) => {
setUserLocation(location);
}
);
const heading = await Location.watchHeadingAsync((heading) => {
setUserHeading(heading.trueHeading);
});
}
};
AccessLocation().catch(console.error);
}, []);
useEffect(() => {
if (userLocation != null) {
setAngle(getBearing() - userHeading);
rotateImage(angle);
}
}, [userLocation]);
const textPosition = JSON.stringify(userLocation);
const getBearing = () => {
const bearing = geolib.getGreatCircleBearing(
{
latitude: userLocation.coords.latitude,
longitude: userLocation.coords.longitude,
},
{
latitude: 45.47200370608976,
longitude: -73.86246549592089,
}
);
return bearing;
};
const rotation = new Animated.Value(0);
console.warn(angle);
const rotateImage = (angle) => {
Animated.timing(rotation, {
toValue: angle,
duration: 1000,
easing: Easing.bounce,
useNativeDriver: true,
}).start();
};
//console.warn(rotation);
return (
<View style={styles.background}>
<Text>{textPosition}</Text>
<Animated.Image
source={require("../../assets/Compass/Arrow_up.png")}
style={[styles.image, { transform: [{ rotate: `${angle}deg` }] }]}
/>
</View>
);
}
const styles = StyleSheet.create({
background: {
backgroundColor: COLORS.background_Pale,
flex: 1,
// justifyContent: "flex-start",
//alignItems: "center",
},
image: {
flex: 1,
// height: null,
// width: null,
//alignItems: "center",
},
scrollView: {
backgroundColor: COLORS.background_Pale,
},
});
I think that the math I'm doing must be wrong because the arrow is pointing random directions spinning like crazy and not going to the coordinate I gave it. Also, I can't seem to use the rotateImage function in a way that rotation would be animated and i'd be able to use it to animate the image/compass. If anyone could help me out i'd really appreciate it I've been stuck on this for literally weeks.
I want to use geo location to show content on the screen if user gave permission,
it worked fine but suddenly it does not work any more
it works fine in firefox
also does not work in the google map either, so i think it is not because of insecure websites
I'm using GeoLocated package
here is the code
const AddUserPage = ({ coords, isGeolocationEnabled }) => {
const [location, setLocation] = useState(null)
useEffect(() => {
if (coords) {
setLocation({ lat: coords.latitude, lng: coords.longitude })
}
}, [coords])
const changeLocation = (location) => {
setLocation(location)
}
if (!isGeolocationEnabled) {
return <div>fuck you</div>
}
if (coords) {
return (
<div style={{ width: '300px', height: "300pc" }}>
<UserMap changeLocation={changeLocation} lat={coords.latitude} lng={coords.longitude}></UserMap>
<Button onClick={()=>{
console.log(location)
}}>current location</Button>
</div>
);
}
return <div>nslknl;ij'poj</div>
};
export default geolocated({
enableHighAccuracy: true,
timeout: 5000,
maximumAge: 0
})(AddUserPage);
I used React Google Maps api in one of my Gatsby sites. I created the following component and imported it into one of my pages. Here is the code for the compenent.
import React, { useState } from "react"
import {
GoogleMap,
useLoadScript,
Marker,
InfoWindow,
} from "#react-google-maps/api"
import { useStaticQuery, graphql } from "gatsby"
import mapStyles from "./mapStyles"
const Indianapolis = {
lat: 39.768402,
lng: -86.158066,
}
const mapContainerStyle = {
height: "100%",
width: "100%",
}
const options = {
styles: mapStyles,
disableDefaultUI: true,
zoomControl: true,
}
const Map = () => {
const data = useStaticQuery(graphql`
{
allKmlPoint {
edges {
node {
properties {
name
Longitude
Latitude
FRP_Project_Numbers
description
styleUrl
styleHash
}
id
}
}
}
}
`)
const [selected, setSelected] = useState(null)
const frpLocation = data.allKmlPoint.edges
//console.log(process.env.GATSBY_GOOGLE_MAPS_API_KEY)
const { isLoaded, loadError } = useLoadScript({
googleMapsApiKey: process.env.GATSBY_GOOGLE_MAPS_API_KEY,
})
const mapRef = React.useRef()
const onMapLoad = React.useCallback(map => {
mapRef.current = map
console.log(map)
}, [])
const onUnmount = React.useCallback(function callback(map) {
console.log(map)
}, [])
if (loadError) return "Error"
if (!isLoaded) {
return "Loading..."
}
//console.log("comes here")
return (
<div className="map-container">
<span className="top-text">Project</span>
<span className="horizontal-line"></span>
<span className="bottom-text">
Locati<span className="full-color">o</span>ns
</span>
<span className="map-blurb">
FRP has a project portfolio across a wide geographic region. Click the
Map to Zoom and pan to the project locations for various market types.
</span>
<div className="map-wrapper">
<GoogleMap
zoom={8}
center={Indianapolis}
mapContainerStyle={mapContainerStyle}
options={options}
onUnmount={onUnmount}
onLoad={onMapLoad}
>
{frpLocation.map(marker => (
<Marker
key={marker.node.id}
position={{
lat: parseFloat(marker.node.properties.Latitude),
lng: parseFloat(marker.node.properties.Longitude),
}}
icon={{
url: `icon_${marker.node.properties.styleUrl.slice(-6)}.svg`,
origin: new window.google.maps.Point(0, 0),
anchor: new window.google.maps.Point(15, 15),
scaledSize: new window.google.maps.Size(30, 30),
}}
onClick={() => {
setSelected(marker)
}}
/>
))}
{selected ? (
<InfoWindow
position={{
lat: parseFloat(selected.node.properties.Latitude),
lng: parseFloat(selected.node.properties.Longitude),
}}
onCloseClick={() => {
setSelected(null)
}}
>
<div>
<p>{selected.node.properties.name}</p>
</div>
</InfoWindow>
) : null}
</GoogleMap>
</div>
</div>
)
}
export default Map
The page works just fine. However, when I try to move away from the page (which has the google map) to another page (in Gatsby), the page transition is not smooth. Gatsby reloads the new page entirely. The console gives me the following error:
Uncaught TypeError: a is undefined
ZU marker.js:48
<anonymous> marker.js:45
setTimeout handler*_.bn common.js:17
<anonymous> marker.js:45
H js:207
trigger js:204
remove js:207
removeListener js:203
unregisterEvent reactgooglemapsapi.esm.js:142
unregisterEvents reactgooglemapsapi.esm.js:150
componentWillUnmount reactgooglemapsapi.esm.js:2118
wrappedMethod react-hot-loader.development.js:707
React 27
unlisten index.js:103
unlisten index.js:101
promise callback*componentDidMount/refs.unlisten< index.js:99
navigate history.js:100
navigate history.js:99
navigate navigation.js:120
promise callback*navigate navigation.js:84
___navigate navigation.js:162
onClick index.js:256
onClick index.js:477
React 22
marker.js:48:38
There are several instances of this error on the console (I think as many as the number of markers I have on my map).
I am sure it is a simple fix to get rid of this error. Can someone help
UPDATE:Based on what #Ferran said, I used the following code, Still does not work:
I created a useState hook as you said.
const [frpMap, setFrpMap] = useState(null)
mapRef.current = map
...
const onLoad = React.useCallback(function callback(map) {
setFrpMap(map)
}, [])
const onUnmount = React.useCallback(function callback(map) {
setFrpMap(null)
mapRef.current = null
//console.log(map)
}, [])
I think I am not sure how to use the map variable set in the setFrpMap hook to render the GoogleMap.
So, when I do setFrpMap(null) on unmount nothing really happens.
You aren't unmounting your map so it breaks when the routing changes. This is not doing anything:
const onUnmount = React.useCallback(function callback(map) {
console.log(map)
}, [])
I would suggest an approach using useState hook, in order to mount and unmount/dispose the map when needed:
import React, { useState } from "react"
import {
GoogleMap,
useLoadScript,
Marker,
InfoWindow,
} from "#react-google-maps/api"
import { useStaticQuery, graphql } from "gatsby"
import mapStyles from "./mapStyles"
const Indianapolis = {
lat: 39.768402,
lng: -86.158066,
}
const mapContainerStyle = {
height: "100%",
width: "100%",
}
const options = {
styles: mapStyles,
disableDefaultUI: true,
zoomControl: true,
}
const Map = () => {
const [map, setMap] = React.useState(null)
const data = useStaticQuery(graphql`
{
allKmlPoint {
edges {
node {
properties {
name
Longitude
Latitude
FRP_Project_Numbers
description
styleUrl
styleHash
}
id
}
}
}
}
`)
const [selected, setSelected] = useState(null)
const frpLocation = data.allKmlPoint.edges
//console.log(process.env.GATSBY_GOOGLE_MAPS_API_KEY)
const { isLoaded, loadError } = useLoadScript({
googleMapsApiKey: process.env.GATSBY_GOOGLE_MAPS_API_KEY,
})
const mapRef = React.useRef()
const onMapLoad = React.useCallback(map => {
mapRef.current = map
setMap(map)
console.log(map)
}, [])
const onUnmount = React.useCallback(function callback(map) {
console.log(map)
setMap(null)
}, [])
if (loadError) return "Error"
if (!isLoaded) {
return "Loading..."
}
//console.log("comes here")
return (
<div className="map-container">
<span className="top-text">Project</span>
<span className="horizontal-line"></span>
<span className="bottom-text">
Locati<span className="full-color">o</span>ns
</span>
<span className="map-blurb">
FRP has a project portfolio across a wide geographic region. Click the
Map to Zoom and pan to the project locations for various market types.
</span>
<div className="map-wrapper">
<GoogleMap
zoom={8}
center={Indianapolis}
mapContainerStyle={mapContainerStyle}
options={options}
onUnmount={onUnmount}
onLoad={onMapLoad}
>
{frpLocation.map(marker => (
<Marker
key={marker.node.id}
position={{
lat: parseFloat(marker.node.properties.Latitude),
lng: parseFloat(marker.node.properties.Longitude),
}}
icon={{
url: `icon_${marker.node.properties.styleUrl.slice(-6)}.svg`,
origin: new window.google.maps.Point(0, 0),
anchor: new window.google.maps.Point(15, 15),
scaledSize: new window.google.maps.Size(30, 30),
}}
onClick={() => {
setSelected(marker)
}}
/>
))}
{selected ? (
<InfoWindow
position={{
lat: parseFloat(selected.node.properties.Latitude),
lng: parseFloat(selected.node.properties.Longitude),
}}
onCloseClick={() => {
setSelected(null)
}}
>
<div>
<p>{selected.node.properties.name}</p>
</div>
</InfoWindow>
) : null}
</GoogleMap>
</div>
</div>
)
}
export default Map
The idea is to initially set as null your map and set it in your onLoad function with:
const onMapLoad = React.useCallback(map => {
mapRef.current = map
setMap(map)
console.log(map)
}, [])
Note: adapt the snippet to your needs.
Since the callback is receiving the map as a parameter, you are able to use it along with useState hook.
On the other hand, use the opposite way when unmounting the map (onUnmount):
const onUnmount = React.useCallback(function callback(map) {
console.log(map)
setMap(null) // alternatively use map.data=null
}, [])
The same approach, your callback is receiving the map though you don't need it so, you can set the map object as null.
You can check the docs for further details.
const onUnmount = React.useCallback(function callback(map) {
map.data = null
}, [])
did the trick
I have a code thats will automatically put a marker and route destination if theres a data in the array. But if the array is null its gets an error. How to run a map even if theres no data in my array.
This is my sample code.
googlemap.js
import React, { useState, useEffect } from 'react';
import {
withGoogleMap,
GoogleMap,
withScriptjs,
Marker,
DirectionsRenderer
} from "react-google-maps";
import "./config";
function MapDirectionsRenderer(props) {
const [directions, setDirections] = useState(null);
const [error, setError] = useState(null);
useEffect(() => {
const { places, travelMode } = props;
const waypoints = places.map(p => ({
location: { lat: p.latitude, lng: p.longitude },
stopover: true
}));
const origin = waypoints.shift().location;
const destination = waypoints.pop().location;
const directionsService = new google.maps.DirectionsService();
directionsService.route(
{
origin: origin,
destination: destination,
travelMode: travelMode,
waypoints: waypoints
},
(result, status) => {
console.log(result)
if (status === google.maps.DirectionsStatus.OK) {
setDirections(result);
} else {
setError(result);
}
}
);
});
if (error) {
return <h1>{error}</h1>;
}
return (
directions && (
<DirectionsRenderer directions={directions} />
)
);
}
const Map = withScriptjs(
withGoogleMap(props => (
<GoogleMap
defaultCenter={props.defaultCenter}
defaultZoom={props.defaultZoom}
>
{props.markers.map((marker, index) => {
const position = { lat: marker.latitude, lng: marker.longitude };
return <Marker key={index} position={position} />;
})}
<MapDirectionsRenderer
places={props.markers}
travelMode={google.maps.TravelMode.DRIVING}
/>
</GoogleMap>
))
);
export default Map;
Map.js
import React, { Component } from 'react';
import { render } from 'react-dom';
import Map from './googlemap';
import "./config";
const googleMapsApiKey = "myapikey";
const places = coordinate;
const App = props => {
const {
loadingElement,
containerElement,
mapElement,
defaultCenter,
defaultZoom
} = props;
return (
<Map
googleMapURL={
'https://maps.googleapis.com/maps/api/js?key=' +
googleMapsApiKey +
'&libraries=geometry,drawing,places'
}
markers={places}
loadingElement={loadingElement || <div style={{height: `100%`}}/>}
containerElement={containerElement || <div style={{height: "80vh"}}/>}
mapElement={mapElement || <div style={{height: `100%`}}/>}
defaultZoom={defaultZoom || 11}
/>
);
};
export default App;
import React, { Component } from 'react';
import { render } from 'react-dom';
import Map from './googlemap';
import "./config";
const googleMapsApiKey = "myapikey";
const places = coordinate;
const App = props => {
const {
loadingElement,
containerElement,
mapElement,
defaultCenter,
defaultZoom
} = props;
return (
<Map
googleMapURL={
'https://maps.googleapis.com/maps/api/js?key=' +
googleMapsApiKey +
'&libraries=geometry,drawing,places'
}
markers={places}
loadingElement={loadingElement || <div style={{height: `100%`}}/>}
containerElement={containerElement || <div style={{height: "80vh"}}/>}
mapElement={mapElement || <div style={{height: `100%`}}/>}
defaultZoom={defaultZoom || 11}
/>
);
};
export default App;
Btw the map will work if there a two routes available if theres 1 or none the map will not show.
Working with React-Native and trying to learn ES6 syntax. I had a similar issue yesterday and got the solution. I added
.bind(this)
to my my function calls and the problem was solved. I ran into the same issue again with another function call and I cannot track down what is going on. The error message is the same.
undefined is not a object (evaluating 'this.props.drawer.open')
The function is:
onClickMenu () {
this.props.drawer.open();
}
and it is being called with this:
onPress={this.onClickMenu.bind(this)}
Here is the entire code. If you see something other than this issue that doesn't look right let me know please! *note I have replaced "var" with "let". From what I've read it is proper ES6 syntax to do that everywhere?
'use strict';
const React = require('react-native');
const {
Text,
View,
Component,
StyleSheet,
SwitchAndroid
} = React;
import { Button } from 'react-native-material-design';
import Store from 'react-native-simple-store';
import Underscore from 'underscore';
import RNGMap from 'react-native-gmaps';
import Polyline from 'react-native-gmaps/Polyline';
import Icon from 'react-native-vector-icons/Ionicons';
import SettingsService from './../settings/settings.service';
//import subdivisions from './subdivisions.json';
import commonStyles from './../common/styles';
let accessToken = null;
let userId = null;
let routeId = null;
let subdivisionId = null;
SettingsService.init('Android');
class Map extends Component {
constructor(props) {
super(props)
this.state = {
odometer: 0,
mapWidth: 300,
mapHeight: 300,
enabled: false,
isMoving: false,
currentLocation: undefined,
locationManager: undefined,
paceButtonIcon: 'Start Trip',
navigateButtonIcon: 'navigate',
paceButtonStyle: commonStyles.disabledButton,
// mapbox
center: {
lat: 40.7223,
lng: -73.9878
},
zoom: 10,
markers: []
}
}
componentDidMount() {
Store.get('token').then((token) => {
accessToken = token.access_token;
userId = token.userId;
});
let me = this,
gmap = this.refs.gmap;
this.locationManager = this.props.locationManager;
// location event
this.locationManager.on("location", function(location) {
console.log('- location: ', JSON.stringify(location));
me.setCenter(location);
gmap.addMarker(me._createMarker(location));
me.setState({
odometer: (location.odometer / 1000).toFixed(1)
});
// Add a point to our tracking polyline
if (me.polyline) {
me.polyline.addPoint(location.coords.latitude, location.coords.longitude);
}
});
// http event
this.locationManager.on("http", function(response) {});
// geofence event
this.locationManager.on("geofence", function(geofence) {});
// error event
this.locationManager.on("error", function(error) {
console.log('- ERROR: ', JSON.stringify(error));
});
// motionchange event
this.locationManager.on("motionchange", function(event) {
me.updatePaceButtonStyle();
});
// getGeofences
this.locationManager.getGeofences(function(rs) {
}, function(error) {
console.log("- getGeofences ERROR", error);
});
SettingsService.getValues(function(values) {
values.license = "eddbe81bbd86fa030ea466198e778ac78229454c31100295dae4bfc5c4d0f7e2";
values.orderId = 1;
values.stopTimeout = 0;
//values.url = 'http://192.168.11.120:8080/locations';
me.locationManager.configure(values, function(state) {
me.setState({
enabled: state.enabled
});
if (state.enabled) {
me.initializePolyline();
me.updatePaceButtonStyle()
}
});
});
this.setState({
enabled: false,
isMoving: false
});
}
_createMarker(location) {
return {
title: location.timestamp,
id: location.uuid,
icon: require("image!transparent_circle"),
anchor: [0.5, 0.5],
coordinates: {
lat: location.coords.latitude,
lng: location.coords.longitude
}
};
}
initializePolyline() {
// Create our tracking Polyline
let me = this;
Polyline.create({
width: 12,
points: [],
geodesic: true,
color: '#2677FF'
}, function(polyline) {
me.polyline = polyline;
});
}
onClickMenu () {
this.props.drawer.open();
}
onClickEnable() {
let me = this;
if (!this.state.enabled) {
this.locationManager.start(function() {
me.initializePolyline();
});
} else {
this.locationManager.resetOdometer();
this.locationManager.stop();
this.setState({
markers: [{}],
odometer: 0
});
this.setState({
markers: []
});
if (this.polyline) {
this.polyline.remove(function(result) {
me.polyline = undefined;
});
}
}
this.setState({
enabled: !this.state.enabled
});
this.updatePaceButtonStyle();
}
onClickPace() {
if (!this.state.enabled) {
return;
}
let isMoving = !this.state.isMoving;
this.locationManager.changePace(isMoving);
this.setState({
isMoving: isMoving
});
this.updatePaceButtonStyle();
}
onClickLocate() {
let me = this;
this.locationManager.getCurrentPosition({
timeout: 30
}, function(location) {
me.setCenter(location);
}, function(error) {
console.error('ERROR: getCurrentPosition', error);
me.setState({
navigateButtonIcon: 'navigate'
});
});
}
onRegionChange() {}
setCenter(location) {
this.setState({
navigateButtonIcon: 'navigate',
center: {
lat: location.coords.latitude,
lng: location.coords.longitude
},
zoom: 16
});
}
onLayout() {
let me = this,
gmap = this.refs.gmap;
this.refs.workspace.measure(function(ox, oy, width, height, px, py) {
me.setState({
mapHeight: height,
mapWidth: width
});
});
}
updatePaceButtonStyle() {
let style = commonStyles.disabledButton;
if (this.state.enabled) {
style = (this.state.isMoving) ? commonStyles.redButton : commonStyles.greenButton;
}
this.setState({
paceButtonStyle: style,
paceButtonIcon: (this.state.enabled && this.state.isMoving) ? 'Stop Trip' : 'Start Trip'
});
}
render() {
return (
<View style={commonStyles.container}>
<View style={commonStyles.topToolbar}>
<Icon.Button name="android-options" onPress={this.onClickMenu.bind(this)} backgroundColor="transparent" size={30} color="#000" style={styles.btnMenu} underlayColor={"transparent"} />
<Text style={commonStyles.toolbarTitle}>Background Geolocation</Text>
<SwitchAndroid onValueChange={this.onClickEnable.bind(this)} value={this.state.enabled} />
</View>
<View ref="workspace" style={styles.workspace} onLayout={this.onLayout.bind(this)}>
<RNGMap
ref={'gmap'}
style={{width: this.state.mapWidth, height: this.state.mapHeight}}
markers={this.state.markers}
zoomLevel={this.state.zoom}
onMapChange={(e) => console.log(e)}
onMapError={(e) => console.log('Map error --> ', e)}
center={this.state.center} />
</View>
<View style={commonStyles.bottomToolbar}>
<Icon.Button name={this.state.navigateButtonIcon} onPress={this.onClickLocate.bind(this)} size={25} color="#000" underlayColor="#ccc" backgroundColor="transparent" style={styles.btnNavigate} />
<Text style={{fontWeight: 'bold', fontSize: 18, flex: 1, textAlign: 'center'}}>{this.state.odometer} km</Text>
<Button raised={true}
text={this.state.paceButtonIcon}
onPress={this.onClickPace.bind(this)}
overrides={{backgroundColor:"#e12429",textColor:"#ffffff"}}
style={this.state.paceButtonStyle}></Button>
<Text> </Text>
</View>
</View>
);
}
};
const styles = StyleSheet.create({
workspace: {
flex: 1
}
});
module.exports = Map;
UPDATE:
debugging via adb in the terminal shows the same error
So here is rest of code. to troubleshoot. I added the project files to a plunker. it is a demo project that i am working with. plunker
'use strict';
const React = require('react-native');
const {
Text,
Component,
StyleSheet,
AppRegistry
} = React;
import Map from './map/map';
import Drawer from 'react-native-drawer';
import Settings from './settings/settings.android';
import Icon from 'react-native-vector-icons/Ionicons';
import BackgroundGeolocation from 'react-native-background-geolocation-android';
global.bgGeo = BackgroundGeolocation;
class App extends Component {
onClickMenu() {
this.props.refs.drawer.open();
}
render() {
return (
<Drawer ref="drawer" side="right" acceptPan={false} content={<Settings drawer={this.refs.drawer} locationManager={BackgroundGeolocation} />}>
<Map drawer={this.refs.drawer} locationManager={BackgroundGeolocation} />
</Drawer>
);
}
};
module.exports = App;
UPDATE:
I dont think you can pass through refs to components in such a way,
certainly it would not work in React and I dont think it would work
in such a way in React-Native either.
I'm not clear why you are trying to .open the Drawer from the
Map component as it looks like the Map component can only be
accessed when the Drawer is open, but, if you want to access parent
behaviours from children a good pattern is to pass through functions
for children to execute (you could argue that this is actually bad
and that passing events around is a more robust pattern).
I've never used the library so I'm not totally clear on its usage but
you can pass functions through like this:
class Application extends Component {
closeControlPanel = () => {
this.refs.drawer.close()
};
openControlPanel = () => {
this.refs.drawer.open()
};
render () {
return (
<Drawer
ref="drawer"
content={<ControlPanel />}
>
<Map onMenuClose={ this.closeControlPanel.bind( this ) } />
</Drawer>
)
}
})
In this case this.props.onMenuClose should be attached to an action, which, when executed will trigger the function from the parent and execute the this.refs.drawer.close function.