Thanks in-advance. I am very new to React.
I'm trying to build an android application with React Native (Expo), PHP and MySQL, which requires live location tracking of salesmen for Admin to monitor.
Can any one please suggest me any idea on Live Location Tracking, even when the salesman's mobile screen is off/screen is locked with application running in background.
Salesman don't need any map component as they have nothing to do with their location. Just a Background Task sending their location details for the Admin, where he can track all his salesman's movement (for whole day) on their field job.
Only one application for both(Admin & Salesman), with dynamic menu based on user type which hides menu items for salesman login.
What is the standard method/process for this job ?
Is their any tutorial which i can follow ?
Any extra suggestions/points which i might be missing.
I have searched the whole internet for few days and i am having difficulty understanding the Expo documentation with very less example. Didn't found any suitable solution.
I just found a solution for my problem, sharing it for anybody who is stuck with the same problem.
Get Users Live Location (every step he takes) with React Native.
Thanks
import React, { Component } from "react";
import { StyleSheet, View } from "react-native";
import MapView from "react-native-maps";
import * as Location from "expo-location";
import * as Permissions from "expo-permissions";
import * as TaskManager from "expo-task-manager";
const LOCATION_TASK_NAME = "background-location-task";
export default class App extends Component {
constructor(props) {
super(props);
this.state = {
region: null,
error: '',
};
}
_getLocationAsync = async () => {
await Location.startLocationUpdatesAsync(LOCATION_TASK_NAME, {
enableHighAccuracy: true,
distanceInterval: 1,
timeInterval: 5000
});
// watchPositionAsync Return Lat & Long on Position Change
this.location = await Location.watchPositionAsync(
{
enableHighAccuracy: true,
distanceInterval: 1,
timeInterval: 10000
},
newLocation => {
let { coords } = newLocation;
// console.log(coords);
let region = {
latitude: coords.latitude,
longitude: coords.longitude,
latitudeDelta: 0.045,
longitudeDelta: 0.045
};
this.setState({ region: region });
},
error => console.log(error)
);
return this.location;
};
async componentWillMount() {
// Asking for device location permission
const { status } = await Permissions.askAsync(Permissions.LOCATION);
if (status === "granted") {
this._getLocationAsync();
} else {
this.setState({ error: "Locations services needed" });
}
userId = (await AsyncStorage.getItem("userId")) || "none";
userName = (await AsyncStorage.getItem("userName")) || "none";
}
render() {
return (
<View style={styles.container}>
<MapView
initialRegion={this.state.region}
showsCompass={true}
showsUserLocation={true}
rotateEnabled={true}
ref={map => {
this.map = map;
}}
style={{ flex: 1 }}
/>
</View>
);
}
}
TaskManager.defineTask(LOCATION_TASK_NAME, async ({ data, error }) => {
if (error) {
console.log(error);
return;
}
if (data) {
const { locations } = data;
let lat = locations[0].coords.latitude;
let long = locations[0].coords.longitude;
userId = (await AsyncStorage.getItem("userId")) || "none";
// Storing Received Lat & Long to DB by logged In User Id
axios({
method: "POST",
url: "http://000.000.0.000/phpServer/ajax.php",
data: {
action: "saveLocation",
userId: userId,
lat,
long
}
});
// console.log("Received new locations for user = ", userId, locations);
}
});
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "#fff"
}
});
Related
I'm trying to retrieve data from an existing database. I recently switched to bare workflow from Expo managed, trying to test react-native-sqlite-storage with TypeORM. However, TypeORM raw query keeps returning an empty array and I have no idea why.
Here's my code and it is based on this example https://dev.to/jgabriel1/expo-sqlite-typeorm-4mn8
DictionaryScreen.js
function DictionaryScreen(props) {
const { ejRepository } = useDatabaseConnection();
const handleinputWord = async () => {
console.log(props.inputWord); //=>this console.logs the text from the input below
try {
const results = await ejRepository.getWordandMean(props.inputWord);
console.log(results); //=> Here I expect an array of the query result but it only returns []
} catch (error) {
console.log(error)
}
}
return(
<View style={styles.searchContainer}>
<MaterialCommunityIcons name="text-search" color="white" size={30}/>
<TextInput
style={styles.input}
onChangeText={props.updateTextInput}
onSubmitEditing={handleinputWord}
value={props.inputWord}
placeholder='Look up the word (Type exactly)'
keyboardType="default"
/>
<StatusBar style='light' />
</View>
)
}
const mapStateToProps = state => {
return {
inputWord: state.inputWord
}
};
const mapDispatchToProps = {updateTextInput};
export default connect(mapStateToProps, mapDispatchToProps) (DictionaryScreen);
repository.ts
export class EJRepository {
private ormRepository: Repository<EJModel>;
constructor(connection: Connection) {
this.ormRepository = connection.getRepository(EJModel);
}
public async getWordandMean(props: any): Promise<EJModel> {
console.log(props); //=> this returns the same text from DictionaryScreen
const results = await this.ormRepository.query(
`SELECT * FROM ejmodel WHERE word LIKE '%${props}%';`, [props]);
return results;
}
}
connection.tsx
interface DatabaseConnectionContextData {
ejRepository: EJRepository;
}
const DatabaseConnectionContext = createContext<DatabaseConnectionContextData>(
{} as DatabaseConnectionContextData,
);
export const DatabaseConnectionProvider: React.FC = ({ children }) => {
const [connection, setConnection] = useState<Connection | null>(null);
const connect = useCallback(async () => {
const createdConnection = await createConnection({
type: 'react-native',
name: "ejdict.v1.0",
database: '***.db',
entities: [EJModel],
location: 'default',
migrations: [ejdict1621603544180],
migrationsRun: true,
synchronize: false,
logging: true,
extra: {createFromLocation: '/Users/***/***/ios/***/www/***.db' }
});
setConnection(createdConnection);
}, []);
useEffect(() => {
if (!connection) {
connect();
}
}, [connect, connection]);
if (!connection) {
return <ActivityIndicator />;
}
return (
<DatabaseConnectionContext.Provider
value={{
ejRepository: new EJRepository(connection),
}}
>
{children}
</DatabaseConnectionContext.Provider>
);
};
export function useDatabaseConnection() {
const context = useContext(DatabaseConnectionContext);
return context;
}
EJModel.ts
import {Entity, PrimaryColumn, Column} from "typeorm";
#Entity({name: "ejmodel"})
export class EJModel {
#PrimaryColumn({type: 'integer'})
item_id: number;
#Column({type: 'text'})
word: string;
#Column({type: 'text'})
mean: string;
#Column({type: 'integer'})
level: number;
}
PS: Is it an unusual attempt to load an existing database on a React Native project? Working examples are almost no existent. I once made it work on Expo, but I realised I needed migration functionality and tried to do the same thing with TypeORM wasting lots of time...
I have found the solution for this problem by following step
adjust the entity of the table to
#Entity({
name: YOUR_TABLE_NAME,
synchronize: false,
})
Put the existed database into dir
android/app/src/main/assets or android/app/src/main/assets/www
Typeorm declare
export const AppDataSource = new DataSource({
type: "react-native",
database: database.db,
location: "default",
synchronize: true,
entities: [YOUR_ENTITY],
logging: ["error", "query", "schema"],
});
//note that can set to false if you want all tables to not synchronize or can set individually in each Entity like step 1.
4) In your index.android.js or App.js file, openDatabase to get connect to the database.
SQLite.openDatabase(
{
name: "database.db",
createFromLocation: "~database23_02_17.db",
location: "default",
},
() => {
console.log("db connection success");
},
() => {
console.log("db connection error");
}
);
Uninstall the app if you've already installed in your physical device (because the app will not update the database file) and then run build again
cd android &&./gradlew clean
cd .. && react-native run-android
I followed the following tutorial in order to have the user's location for my react native app:
https://reactnativemaster.com/react-native-geolocation-example/
However, nothing is showing apart from the Hello on my iphone.
I think that the problem is that geocode is null but I do not know how to fix it.
Any tips would be helpful :)
Please see my code below if needed:
import React, { Component } from "react";
import {
StyleSheet,
Text,
View,
} from "react-native";
import * as Location from 'expo-location';
import * as Permissions from 'expo-permissions';
class App extends Component {
state= {
location:null,
geocode:null,
errorMessage:""
}
getLocationAsync = async () => {
let { status } = await Permissions.askAsync(Permissions.LOCATION);
if (status !== 'granted') {
this.setState({
errorMessage: 'Permission to access location was denied',
});
}
let location = await Location.getCurrentPositionAsync({accuracy:Location.Accuracy.Highest});
const { latitude , longitude } = location.coords
this.getGeocodeAsync({latitude, longitude})
this.setState({ location: {latitude, longitude}});
};
getGeocodeAsync= async (location) => {
let geocode = await Location.reverseGeocodeAsync(location)
this.setState({ geocode})
}
render(){
const {location,geocode, errorMessage } = this.state
return (
<View style={styles.overlay}>
<Text>Hello</Text>
<Text style={styles.heading1}>{geocode ? `${geocode[0].city}, ${geocode[0].isoCountryCode}` :""}</Text>
<Text style={styles.heading2}>{geocode ? geocode[0].street :""}</Text>
<Text style={styles.heading3}>{location ? `${location.latitude}, ${location.longitude}` :""}</Text>
<Text style={styles.heading2}>{errorMessage}</Text>
</View>
);
}
}
export default App;
import React, { Component } from "react";
import {
StyleSheet,
Text,
View,
} from "react-native";
import * as Location from 'expo-location';
import * as Permissions from 'expo-permissions';
class App extends Component {
state= {
location:null,
geocode:null,
errorMessage:""
}
// You have to call this.getLocationAsync()
componentDidMount(){
// this is needed for geocode
Location.setApiKey("Your-API-KEY-Here")
this.getLocationAsync();
}
getLocationAsync = async () => {
let { status } = await Permissions.askAsync(Permissions.LOCATION);
if (status !== 'granted') {
this.setState({
errorMessage: 'Permission to access location was denied',
});
}
let location = await Location.getCurrentPositionAsync({accuracy:Location.Accuracy.Highest});
const { latitude , longitude } = location.coords
this.setState({ location: {latitude, longitude}});
this.getGeocodeAsync({latitude, longitude}).catch(err => {this.setState({errorMessage: err})})
};
getGeocodeAsync= async (location) => {
let geocode = await Location.reverseGeocodeAsync(location)
this.setState({geocode: geocode})
// check console for geocode response
console.log(geocode)
}
render(){
const {location,geocode, errorMessage } = this.state
return (
<View style={styles.overlay}>
<Text>Hello</Text>
<Text style={styles.heading1}>{geocode ? `${geocode[0].city}, ${geocode[0].region}` :""}</Text>
<Text style={styles.heading2}>{geocode ? geocode[0].country :""}</Text>
<Text style={styles.heading3}>{location ? `${location.latitude}, ${location.longitude}` :""}</Text>
<Text style={styles.heading2}>{errorMessage}</Text>
</View>
);
}
}
// Create styles for your headings here
const styles = StyleSheet.create({
heading1:{
fontSize: 24
},
heading2:{
fontSize: 18
},
heading3:{
fontSize: 12
}
})
export default App;
You need to use your google API key for the geocode service so it won't return null and if you run this without it you should setState for error message to display for geocode.
Right now I am trying to console.log this.streamCreatorUid, but I'm running into a peculiar issue. In my redux debugger, I can clearly see my data in the proper place.
Here is my redux data for the stream creator, directly from my debugger.
streams -
[0] -
{category(pin): "Oldschool Runescape"
displayName(pin): "admin"
streamId(pin): "98ebc719-c7d5-4558-b99d-2d9f8306ec64"
title(pin): "accounttest"
uid(pin): "wsFc7pIMq5dMtw9hPU86DzUTdLO2"
}
I am trying to console.log this.streamCreatorUid from my mapstatetoprops, but it is returning the current user Uid of u9TcrICehNMlAmqyDHQY77L9CXq1 instead. I'm quite confused as to why this is happening, considering this is not the data shown in my debugger.
This is for a personal project. In the past I've accessed redux props like this with no issues, now I'm not quite sure why this is happening.
import React from 'react';
import { database } from '../../../firebaseconfig.js';
import { connect } from 'react-redux';
class StreamFollow extends React.Component {
constructor(props) {
super(props);
this.uid = this.props.uid;
this.displayName = this.props.displayName;
this.streamCreatorUid = this.props.streamCreatorUid;
this.streamCreatorDisplayName = this.props.streamCreatorDisplayName;
}
componentShouldUpdate(prevProps) {
if (this.props.uid !== prevProps.uid) {
this.uid = this.props.uid
}
if (this.props.streamCreatorUid !== prevProps.streamCreatorUid) {
this.streamCreatorUid = this.props.streamCreatorUid;
}
}
//creates a follower object under the stream creators uid
createFollower = (e) => {
const followerRef = database.ref(`User_Follow_Info/${e}/Follower`)
const followerInfoObject = {
uid: this.uid,
displayName: this.displayName
}
followerRef.push(followerInfoObject);
}
//creates a following object under the users uid
//Add in checks to see if following object already exists. We can't follow someone multiple times
createFollowing = (user) => {
const followingRef = database.ref(`User_Follow_Info/${user}/Following`);
const followingInfoObject = {
uid: this.streamCreatorUid,
displayName: this.streamCreatorDisplayName
}
console.log(this.streamCreatorDisplayName)
//Check to see if follow already exists.
/*followingRef.once('value', function (snapshot) {
if (snapshot.hasChild(DATA HERE)) {
alert('exists');
}
}); */
var isSignedIn = this.isSignedIn;
followingRef.orderByChild('uid').equalTo(this.uid).once('value').then(snapshot => {
console.log(snapshot.val());
console.log(this.streamCreatorUid);
if (isSignedIn) {
console.log(snapshot.val())
return
} else {
followingRef.push(followingInfoObject);
}
})
}
onSubmit = () => {
if (this.props.isSignedIn === true) {
this.createFollowing(this.uid);
this.createFollower(this.streamCreatorUid);
} else {
//add in a sign in modal if user is not logged in
console.log('please sign in')
}
}
render() {
return (
<div>
<button onClick={this.onSubmit}>Follow</button>
</div>
);
}
}
const mapStateToProps = (state) => {
return {
isSignedIn: state.auth.isSignedIn,
displayName: state.auth && state.auth.userInfo ? state.auth.userInfo.displayName : null,
uid: state.auth && state.auth.userInfo ? state.auth.userInfo.uid : null,
streamCreatorUid: state.streams && state.streams[0] ? state.streams[0].uid : null,
streamCreatorDisplayName: state.streams && state.streams[0] ? state.streams[0].displayName : null,
}
}
export default connect(mapStateToProps)(StreamFollow);
I have geolocation running in my app. In Xiaomi device in which i'm working on works fine. I tried on 2 other devices, and got Location request timed out error. Here's the code i have:
import React, { Component } from 'react'
import { View, AsyncStorage, Dimensions, PermissionsAndroid } from 'react-native';
const { width, height } = Dimensions.get('window')
const ASPECT_RATIO = width / height
const LATITUDE_DELTA = 0.0922
const LONGITUDE_DELTA = LATITUDE_DELTA * ASPECT_RATIO
class App extends Component {
constructor(props) {
super(props)
this.state = {
initialPosition: {
latitude: null,
longitude: null,
latitudeDelta: null,
longitudeDelta: null
}
}
}
requestLocationPermission = async () => {
try {
const granted = await PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,
{
'title': 'Location Permission',
'message': 'This App needs access to your location ' +
'so we can know where you are.'
}
)
if (granted === PermissionsAndroid.RESULTS.GRANTED) {
console.log("You can use locations ")
navigator.geolocation.getCurrentPosition((position) => {
let lat = parseFloat(position.coords.latitude)
let long = parseFloat(position.coords.longitude)
let initialRegion = {
latitude: lat,
longitude: long,
latitudeDelta: LATITUDE_DELTA,
longitudeDelta: LONGITUDE_DELTA
}
this.setState({ initialPosition: initialRegion })
this.setState({ markerPosition: initialRegion })
},
(error) => alert(JSON.stringify(error)),
{ enableHighAccuracy: false, timeout: 5000, maximumAge: 10000 }
)
} else {
console.log("Location permission denied")
}
} catch (err) {
console.warn(err)
}
}
componentDidMount() {
this.requestLocationPermission()
}
}
export default App
Some additional information:
React Native version: 0.57.8
Platform: Android
Dev tools: Android SDK v27
i have tried switching enableHighAccuracy to false but that didn't help. The error i get is like this:
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.