Use map instance outside onLoad in react-google-maps - google-maps

I am trying to use places library, It requires map instance to call the library but map instance is only available inside onLoad, I am trying to use the places library whenever the center change(inside onCenterChange).
import React, { useEffect, useState, useCallback } from 'react';
import { GoogleMap, useJsApiLoader } from '#react-google-maps/api';
import GoogleMapReact from 'google-map-react';
import List from './List'
export default function Nearby(){
const { isLoaded, loadError } = useJsApiLoader({
googleMapsApiKey: "My_Key"
})
const onLoad = useCallback(
function onLoad (map) {
var loc= new window.google.maps.LatLng(6.9270786, 79.861243);
var request = {
location: loc,
radius: '500',
type: ['hospital'],
};
function callback(results, status) {
if (status === window.google.maps.places.PlacesServiceStatus.OK) {
console.log(results)
}
}
let service = new window.google.maps.places.PlacesService(map);
service.nearbySearch(request,callback)
}
)
function onCenterChanged(){
//Need to use service.nearbySearch(request,callback) here
}
return(
<div className='map-container'>
<div className = 'google-map'>
<GoogleMap mapContainerStyle={{ height: '91vh', width: '75vw' }}
zoom={14}
onLoad={onLoad}
center= { currentPos}
onCenterChanged={onCenterChanged()}
>
</GoogleMap>
</div>
</div>
)
}

Related

Shopify - How do I route between pages

I am new to Shopify App development and I try to implement routing inside my embedded Shopify App.
I have setup the ClientRouter and also integrated it inside the app.js (see below). When I set Navigation Links through the partners Account, the navigation menu appears and the links and the redirecting work as well.
As soon as I try to navigate the user to a page on a Button click, I get the error:
Expected a valid shop query parameter
I am trying to navigate the user by just giving the path for the page:
<Button url="/users">Users</Button>
My other files are listed below:
index.js
import { Page, Heading, Button } from "#shopify/polaris";
const Index = () => (
<Page>
<Heading>Index PAGE</Heading>
<Button url="/users"> Users </Button>
</Page>
);
export default Index;
app.js
import ApolloClient from "apollo-boost";
import { ApolloProvider } from "react-apollo";
import App from "next/app";
import { AppProvider } from "#shopify/polaris";
import { Provider, useAppBridge } from "#shopify/app-bridge-react";
import { authenticatedFetch } from "#shopify/app-bridge-utils";
import { Redirect } from "#shopify/app-bridge/actions";
import "#shopify/polaris/dist/styles.css";
import translations from "#shopify/polaris/locales/en.json";
import ClientRouter from "../components/ClientRouter";
function userLoggedInFetch(app) {
const fetchFunction = authenticatedFetch(app);
return async (uri, options) => {
const response = await fetchFunction(uri, options);
if (
response.headers.get("X-Shopify-API-Request-Failure-Reauthorize") === "1"
) {
const authUrlHeader = response.headers.get(
"X-Shopify-API-Request-Failure-Reauthorize-Url"
);
const redirect = Redirect.create(app);
redirect.dispatch(Redirect.Action.APP, authUrlHeader || `/auth`);
return null;
}
return response;
};
}
function MyProvider(props) {
const app = useAppBridge();
const client = new ApolloClient({
fetch: userLoggedInFetch(app),
fetchOptions: {
credentials: "include",
},
});
const Component = props.Component;
return (
<ApolloProvider client={client}>
<Component {...props} />
</ApolloProvider>
);
}
class MyApp extends App {
render() {
const { Component, pageProps, host } = this.props;
return (
<AppProvider i18n={translations}>
<Provider
config={{
apiKey: API_KEY,
host: host,
forceRedirect: true,
}}
>
<ClientRouter />
<MyProvider Component={Component} {...pageProps} />
</Provider>
</AppProvider>
);
}
}
MyApp.getInitialProps = async ({ ctx }) => {
return {
host: ctx.query.host,
API_KEY: process.env.SHOPIFY_API_KEY,
};
};
export default MyApp;
ClientRouter.js
import { withRouter } from "next/router";
import { ClientRouter as AppBridgeClientRouter } from "#shopify/app-bridge-react";
function ClientRouter(props) {
const { router } = props;
return <AppBridgeClientRouter history={router} />;
}
export default withRouter(ClientRouter);
I am really looking forward to someone who can help me out! Thanks in advance!

Initializing Google Maps inside component but inside certain element

I using this tutorial to use Google maps API https://markus.oberlehner.net/blog/using-the-google-maps-api-with-vue/ and it is working well. But it use this.$el to load the Google map instance inside the component and that makes take all screen, I want to load inside .map instead so I can have smaller map.
<template>
<div class="container-fluid">
init map
<div class="map">
</div>
</div>
</template>
<script>
import ProgressSpinner from '.././Preloader';
import { mapGetters } from 'vuex'
import gmapsInit from '../.././utils/gmaps';
export default {
name: 'Tracking',
data: () => ({
}),
async mounted() {
$('.container-fluid').bootstrapMaterialDesign();
try {
const google = await gmapsInit();
const geocoder = new google.maps.Geocoder();
const map = new google.maps.Map(this.$el);
geocoder.geocode({ address: 'Austria' }, (results, status) => {
if (status !== 'OK' || !results[0]) {
throw new Error(status);
}
map.setCenter(results[0].geometry.location);
map.fitBounds(results[0].geometry.viewport);
});
} catch (error) {
console.error('Error with calling Google maps API: ',error);
}
},
computed: {
...mapGetters([])
},
created(){
this.$store.dispatch ('allPoints')
.then(()=> console.log('points'))
.catch( () => console.log('no poiints ') )
},
methods: {
},
components: {
ProgressSpinner
}
}
</script>
<style scoped>
.map {
width: 150px;
}
</style>
The problem with style, so I should have added height to the .map element.

react native react-native-geocoding address will not render

i am creating an app to display user add using react native
after getting user permission and latitude,longitude using expo i used react-native-geocoding to turn cords to address but address would not display
expo permission code
import React from 'react';
import { Alert,Platform,StyleSheet, Text, View } from 'react-native';
import { Constants, Location, Permissions } from 'expo';
import AppStackNav from '../party/src/nav/appStackNav';
import Geocoder from 'react-native-geocoding';
Geocoder.init('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx');
export default class App extends React.Component {
state = {
location: null,
errorMessage: null,
addressComponent: null,
};
componentWillMount() {
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({
enableHighAccuracy: true,
});
this.setState({ location });
let lat = this.state.location.coords.latitude;
let long = this.state.location.coords.longitude;
Geocoder.from(lat,long).then(json =>
{
var addressComponent = json.results[0].formatted_address;
this.setState({addressComponent})
// Alert.alert(this.state.addressComponent)
})
}
then attempt to display the address while passing as a prop
import React, {Component} from 'react';
import {View,Text,StyleSheet,FlatList} from 'react-native'
import styles from '../style/styles';
class SetConn extends Component {
render(){
return(
<View>
<Text style={styles.addyComp}>{this.props.addressComponent}</Text>
</View>
);
}
}
export default SetConn;
the react-native-geocoder api works from human readable address -> latitude longitude.
Use google reverse geocoding instead.

JSON format of SVG inside React Component

I used bodymovin extension of AfterEffects to create an animation and export it as a JSON that is compatible for the web. I tried following this walk-through to figure out how to include it inside a component: https://gist.github.com/prettyhandsome/caa7386dcda76fde28cf5d2a07a12082#file-devmyndshapes-jsx
However, I had no luck. Is there a good, step by step resource online for how to include JSON as an image inside a React component? Here is my failed attempt:
import React, { Component } from 'react';
import Plx from 'react-plx';
import PropTypes from 'prop-types';
import bodymovin from 'bodymovin';
import animationData from '../../animations/test.json';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import { skyChange } from './redux/actions';
export class Home extends Component {
static propTypes = {
home: PropTypes.object.isRequired,
actions: PropTypes.object.isRequired,
};
componentDidMount() {
this.attachAnimation();
}
animationIsAttached = false;
const animationProperties = {
//the is the DOM element that you would like to attach your animation to
container: this.animationContainer,
//the renderer options are svg, canvas, or html
renderer: 'svg',
//true plays the animation in a continuous loop
loop: true,
//true plays the animation when the view loads
autoplay: true,
//the JSON data, which we imported above
animationData: animationData
}
attachAnimation = () => {
if (this.animationContainer !== undefined && !this.animationIsAttached) {
const animationProperties = {
container: this.animationContainer,
renderer: 'svg',
loop: true,
autoplay: true,
animationData: animationData
}
bodymovin.loadAnimation(animationProperties);
}
}
render() {
const { skyState, splashState } = this.props.home;
const { skyChange } = this.props.actions;
return (
<div className="testing-animation">
<h1> Animation Attempt </h1>
<div style={{width: 50, height: 50}} ref={(animationDiv) => { this.animationContainer = animationDiv; }}/>
</div>
</div>
);
}
}
/* istanbul ignore next */
function mapStateToProps(state) {
return {
home: state.home,
};
}
/* istanbul ignore next */
function mapDispatchToProps(dispatch) {
return {
actions: bindActionCreators({ skyChange }, dispatch)
};
}
export default connect(
mapStateToProps,
mapDispatchToProps
)(Home);
Replace the code -
animationData: animationData
to
animationData: animationData.default

React+Redux - show InfoWindow on Marker click

I would like to display InfoWindow on Marker click. I followed some tutorials and I used react-google-maps for my project. I would like my app to work like this: "https://tomchentw.github.io/react-google-maps/basics/pop-up-window" but my code is a little bit different.
class Map extends React.Component {
handleMarkerClick(){
console.log("Clicked");
}
handleMarkerClose(){
console.log("CLOSE");
}
render(){
const mapContainer= <div style={{height:'100%',width:'100%'}}></div>
//fetch markers
const markers = this.props.markers.map((marker,i) => {
return (
<Marker key={i} position={marker.location} showTime={false} time={marker.time} onClick={this.handleMarkerClick} >
{
<InfoWindow onCloseClick={this.handleMarkerClose}>
<div>{marker.time}</div>
</InfoWindow>
}
</Marker>
)
})
/* set center equals to last marker's position */
var centerPos;
if(markers[markers.length-1]!== undefined)
{
centerPos=markers[markers.length-1].props.position;
}
else {
centerPos={};
}
return (
<GoogleMapLoader
containerElement={mapContainer}
googleMapElement={
<GoogleMap
defaultZoom={17}
center={centerPos}
>
{markers}
</GoogleMap>
}/>
);
}
}
export default Map;
I got "this.props.markers" from another class component, which fetching data from URL. I am almost sure, that it is easy problem to solve. Currently on marker click in console I got "Clicked" and on Marker close "CLOSE" as you can guess from above code it is because of handleMarkerClick() and handleMarkerClose(). I want to have pop-window with InfoWindow.
What should I do to make it work?
Here is heroku link : App on heroku
Hi I came across the same requirement. I did this (I am using redux and redux-thunk) :
GoogleMap.js
import React, { Component } from 'react';
import { connect } from 'react-redux';
import {
withGoogleMap,
GoogleMap,
Marker,
InfoWindow
} from 'react-google-maps';
import { onMarkerClose } from '../actions/Cabs';
const GettingStartedGoogleMap = withGoogleMap(props => (
<GoogleMap
defaultZoom={12}
defaultCenter={{ lat: 12.9716, lng: 77.5946 }}
>
{props.markers.map( (marker, index) => (
<Marker {...marker} onClick={() => props.onMarkerClose(marker.key)}>
{marker.showInfo &&(
<InfoWindow onCloseClick={() => props.onMarkerClose(marker.key)}>
<div>
<h1>Popover Window</h1>
</div>
</InfoWindow>
)}
</Marker>
))}
</GoogleMap>
));
class CabType extends Component{
constructor(props){
super(props);
}
render(){
if(this.props.cabs.length === 0){
return <div>loading...</div>
}
return(
<div className="map-wrapper">
<GettingStartedGoogleMap
containerElement={
<div style={{ height: '100%' }} />
}
mapElement={
<div style={{ height: '100%' }} />
}
onMarkerClose = {this.props.onMarkerClose}
markers={this.props.showMap ? this.props.markers : []}
/>
</div>
)
}
}
export default connect(store => {return {
cabs : store.cabs,
markers: store.markers
}}, {
onMarkerClose
})(CabType);
Action.js
const getMarkers = (cabs , name) => dispatch => {
let markers = [];
let data = {};
cabs.map(cab => {
if(cab.showMap){
data = {
position: {
lat : cab.currentPosition.latitude,
lng : cab.currentPosition.longitude
},
showInfo: false,
key: cab.cabName,
icon: "/images/car-top.png",
driver: cab.driver,
contact: cab.driverContact,
};
markers.push(data);
}
});
dispatch(emitMarker(markers));
};
function emitSetMarker(payload){
return{
type: SET_MARKER,
payload
}
}
export const onMarkerClose = (key) => dispatch => {
dispatch(emitSetMarker(key))
};
RootReducer.js
import { combineReducers } from 'redux';
import { cabs } from "./Cabs";
import { markers } from "./Markers";
const rootReducer = combineReducers({
cabs,
markers,
});
export default rootReducer;
MarkerReducer.js
import { GET_MARKERS, SET_MARKER } from "../types"
export const markers = (state = [], action) => {
switch (action.type){
case GET_MARKERS:
return action.payload;
case SET_MARKER:
let newMarker = state.map(m => {
if(m.key === action.payload){
m.showInfo = !m.showInfo;
}
return m;
});
return newMarker;
default: return state;
}
};
Sorry for a long post but this is code which is tested and running. Cheers!