Change the height and width on a google map in React js - reactjs

Hi guys i am working on a small presentation project. I need make a google map with the ability to auto search location. I found a code what does all that from a tutorial but i can't change the width and the height. I need it to be small, something like: height: 200px and width: 200px.
GoogleMap.js
import React, { Component } from 'react';
import {Map, Marker, GoogleApiWrapper} from 'google-maps-react';
import PlacesAutocomplete, {
geocodeByAddress,
getLatLng,
} from 'react-places-autocomplete';
export class MapContainer extends Component {
constructor(props) {
super(props);
this.state = {
// for google map places autocomplete
address: '',
showingInfoWindow: false,
activeMarker: {},
selectedPlace: {},
mapCenter: {
lat: 49.2827291,
lng: -123.1207375
}
};
}
handleChange = address => {
this.setState({ address });
};
handleSelect = address => {
this.setState({ address });
geocodeByAddress(address)
.then(results => getLatLng(results[0]))
.then(latLng => {
console.log('Success', latLng);
// update center state
this.setState({ mapCenter: latLng });
})
.catch(error => console.error('Error', error));
};
render() {
return (
<div id='googleMaps'>
<PlacesAutocomplete
value={this.state.address}
onChange={this.handleChange}
onSelect={this.handleSelect}
>
{({ getInputProps, suggestions, getSuggestionItemProps, loading }) => (
<div>
<input
{...getInputProps({
placeholder: 'Search Places ...',
className: 'location-search-input',
})}
/>
<div className="autocomplete-dropdown-container">
{loading && <div>Loading...</div>}
{suggestions.map(suggestion => {
const className = suggestion.active
? 'suggestion-item--active'
: 'suggestion-item';
// inline style for demonstration purpose
const style = suggestion.active
? { backgroundColor: '#fafafa', cursor: 'pointer' }
: { backgroundColor: '#ffffff', cursor: 'pointer' };
return (
<div
{...getSuggestionItemProps(suggestion, {
className,
style,
})}
>
<span>{suggestion.description}</span>
</div>
);
})}
</div>
</div>
)}
</PlacesAutocomplete>
<Map
google={this.props.google}
initialCenter={{
lat: this.state.mapCenter.lat,
lng: this.state.mapCenter.lng
}}
center={{
lat: this.state.mapCenter.lat,
lng: this.state.mapCenter.lng
}}
>
<Marker
position={{
lat: this.state.mapCenter.lat,
lng: this.state.mapCenter.lng
}} />
</Map>
</div>
)
}
}
export default GoogleApiWrapper({
apiKey: ('_MY_API_KEY_')
})(MapContainer)
App.js
import './App.css';
import GoogleMap from './components/GoogleMap';
function App() {
return (
<div className="App">
<h1>Google Maps App</h1>
<GoogleMap />
</div>
);
}
export default App;
I have error in the console but I don't know if they are connected with this problem.
Here they are:
Warning: Using UNSAFE_componentWillReceiveProps in strict mode is not recommended and may indicate bugs in your code. See https://reactjs.org/link/unsafe-component-lifecycles for details.
Move data fetching code or side effects to componentDidUpdate.
If you're updating state whenever props change, refactor your code to use memoization techniques or move it to static getDerivedStateFromProps. Learn more at: https://reactjs.org/link/derived-state
Please update the following components: Wrapper
Warning: Can't call setState on a component that is not yet mounted. This is a no-op, but it might indicate a bug in your application. Instead, assign to this.state directly or define a state = {}; class property with the desired state in the Wrapper component.
index.js:1 Warning: Using UNSAFE_componentWillReceiveProps in strict mode is not recommended and may indicate bugs in your code. See https://reactjs.org/link/unsafe-component-lifecycles for details.
Move data fetching code or side effects to componentDidUpdate.
If you're updating state whenever props change, refactor your code to use memoization techniques or move it to static getDerivedStateFromProps. Learn more at: https://reactjs.org/link/derived-state
Please update the following components: Wrapper
I saw that other people had this problem also but their solutions didn't help me. Any advice is much appreciated!

You can try to wrap the map container in a div and set it's height and width using css. I think that should work

Just have a small change in div created by the script. It should work
return (
<div id='googleMaps' style="width:200px; height:200px">
<PlacesAutocomplete

Related

ReactJS useState, onClick show InfoWindow

In my react google maps code I am not able to set onclick open InfoWindow. I am referring to this tutorial: https://youtu.be/WZcxJGmLbSo?t=1545
my code:
import React, { useState } from "react";
import {
GoogleMap,
useLoadScript,
Marker,
InfoWindow,
} from "#react-google-maps/api"; // --> using #react package
const libraries = ["places"];
const mapContainerStyle = {
width: "100%",
height: "100vh",
};
const center = {
lat: 51.103807,
lng: 10.057477,
};
export default function App() {
const [setSState, sstate] = React.useState(null);
const { isLoaded, loadError } = useLoadScript({
googleMapsApiKey: process.env.REACT_APP_GOOGLE_KEY,
libraries,
});
if (loadError) return "error loading maps";
if (!isLoaded) return "loading maps";
return (
<div>
<GoogleMap
mapContainerStyle={mapContainerStyle}
zoom={6}
center={{ lat: 50.115509, lng: 8.690508 }}
>
<Marker
position={{ lat: 51.081753, lng: 13.696073 }}
onClick={() => {
sstate(!setSState);
console.log("marker clicked");
}}
}}
></Marker>
</GoogleMap>
</div>
);
}
I am not able to show the marker only when clicked. What shall I do? I am hard coding the data for now. I am still new to props.
And when click the X on marker and click on the marker again it crashes. I know I have to use onCloseClick which when I tried didnt work.
Have a look at the useState Hook docs.
The hook will give you a state variable to use, and a function that can be used to update that variable.
At the top of the component you want to have:
const [centerState, setCenterState] = useState(null);
and then you can use this in the Marker to update the state:
onClick={() => setCenterState(center)}
That will update the state, but in your code you are currently getting center from an object assigned outside of the component, you might want to think about what you are going to set in that state.

Is this the correct usage of React Components?

I am new to React. I want to share my components files with you. The code is syntactically correct and executes just fine. I just want to know, if its logically correct and the correct use of concepts such as states.
Is it correct to save lng and lat coords from the GeoLocation API to the MapContainer State?
Is it the correct use of ComponentDidMount() function.
What other ways can I improve the code.
// Map.js
import React from 'react'
import 'bootstrap/dist/css/bootstrap.css';
import GoogleMapReact from 'google-map-react';
function Map(props) {
const screenHeight = window.screen.height;
return (
<div style={{ height: screenHeight - 250 }}>
<GoogleMapReact
bootstrapURLKeys={{ key: "123mykey" }}
center={props.center}
defaultZoom={props.zoom}
></GoogleMapReact>
</div>
);
}
Map.defaultProps = {
center: {
lat: 59.95,
lng: 30.33
},
zoom: 11
};
export default Map
// MapContainer.js
import React from 'react'
import 'bootstrap/dist/css/bootstrap.css';
import Map from './Map'
class MapContainer extends React.Component {
constructor(props) {
super(props);
this.state = {
center: {
lat: 0, lng: 0
}
}
this.getLocation = this.getLocation.bind(this);
this.showPosition = this.showPosition.bind(this);
}
getLocation() {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(this.showPosition);
} else {
console.log("Geolocation is not supported by this browser.");
}
}
showPosition(position) {
this.setState({
center: {
lat: position.coords.latitude,
lng: position.coords.longitude
}
});
}
componentDidMount() {
this.getLocation();
}
render() {
return (
<div className="row">
<div className="col-md-9">
<Map center={this.state.center} />
</div>
<div className="col-md-3 d-sm-none d-md-block d-none d-sm-block">
<h1>Menu</h1>
</div>
</div>
);
}
}
export default MapContainer
Looks fine to me. You only need to import 'bootstrap/dist/css/bootstrap.css'; in your main index.js file.
Everything seems good, you are doing right
Is it correct to save lng and lat coords from the GeoLocation API to the MapContainer State?
Is it the correct use of ComponentDidMount() function?
Yeah, Why not ?
What other ways can I improve the code.
there are some minor changes like:
1- you can import Component on top and the class definition would be smaller
2- it is a good practice to use arrow function component definition like this
export default (props) => {
const screenHeight = window.screen.height;
return (
<div style={{ height: screenHeight - 250 }}>
<GoogleMapReact
bootstrapURLKeys={{ key: "AIzaSyCV1fQD2VC6HoNbuuSPkE0q_QZvDf117PY" }}
center={props.center}
defaultZoom={props.zoom}
></GoogleMapReact>
</div>
);
}
generally you are using react in right way, keep going
It looks fine at MapContainer (Example 2) but I propose separate your view based logics and the others. For example, the getLocation function is not based on your view (not depending React component or changing the view) so we can plug out this logic function into an independent function later the showPosition function is going to use that function.

Make onClick on <li> go to another view

i'm new on react and i'm doing a project, actually it's a to do list, and i need to make a router that when i click on my item on they send me to details of this item. Here's my actual code. That's my app.js
import React, { Component } from 'react';
import List from './List';
export default class App extends Component {
constructor(props) {
super(props);
this.state = {
term: '',
items: []
};
}
onChange = (event) => {
this.setState({ term: event.target.value });
}
onSubmit = (event) => {
event.preventDefault();
this.setState({
term: '',
items: [...this.state.items, this.state.term]
});
}
render() {
return (
<div style={{display: "flex", flexDirection: 'column', alignItems: "center", margin: 5}}>
<form onSubmit={this.onSubmit}>
<input style={{borderRadius: 3, borderColor: "black"}}
value={this.state.term} onChange={this.onChange} />
<button style={{borderRadius: 3, borderColor: "black"}}>
Adicionar</button>
</form>
<List items={this.state.items}/>
</div>
);
}
}
And here my List.js
import React from 'react';
const List = ({ items }) => (
<ul style={{display: "block", listStyleType: "none", backgroundColor: "red"}}>
{
items && items.map((item, index) => <li key={index}>{item}</li>)
}
</ul>
);
export default List;
So i now i will have to use some library to make the route, but first i need to know how i make my itens clickable and when i click they return something that can i redirect to a detail view. Make sense?
And there's a library that you guys recommend to do this job?
Thank you
As i think, you need to use custom links in react As:
1) npm i react-router-dom
2) import {Link} from 'react-router-dom';
3) And finally use <Link to="paste_your_url_here" />
you can also place <Link to='' /> inside of ul, li.
You could add a onClick on each li that redirects to the url you want (implementation may vary based off the lib you choose to handle rooting), but that's not really a good idea since in HTML li are not supposed to be clickable.
What I would do is have a link (again, see with the routing lib - generally it provides a <Link /> component) inside each <li>. This provides better semantic to your code.
Hope this makes sense.
As for a good library... React-router or reach-router are pretty nice!

react-leaflet get current latlng onClick

I would be realy happy if some one could help me...
I've installed react-leaflet on my react project and the map component is loaded successfully, i need to get current latlng and show it in the Popup when i click on map but I don't know how to :(
please... please... help me...
this is my code
import React from 'react'
import { Map as LeafletMap, TileLayer, Marker, Popup } from 'react-leaflet';
class Mapp extends React.Component {
componentDidMount() {
}
render() {
return (
<LeafletMap
center={[35.755229,51.304470]}
zoom={16}
maxZoom={20}
attributionControl={true}
zoomControl={true}
doubleClickZoom={true}
scrollWheelZoom={true}
dragging={true}
animate={true}
easeLinearity={0.35}
>
<TileLayer
url='http://{s}.tile.osm.org/{z}/{x}/{y}.png'
/>
<Marker position={[35.755229,51.304470]}
draggable={true}
>
<Popup >
Popup for any custom information.
</Popup>
</Marker>
</LeafletMap>
);
}
}
export default Mapp;
Here is an example on how to display maker position in popup once map is clicked:
class MapExample extends Component {
constructor(props) {
super(props);
this.state = {
currentPos: null
};
this.handleClick = this.handleClick.bind(this);
}
handleClick(e){
this.setState({ currentPos: e.latlng });
}
render() {
return (
<div>
<Map center={this.props.center} zoom={this.props.zoom} onClick={this.handleClick}>
<TileLayer
url='http://{s}.tile.osm.org/{z}/{x}/{y}.png'
/>
{ this.state.currentPos && <Marker position={this.state.currentPos} draggable={true}>
<Popup position={this.state.currentPos}>
Current location: <pre>{JSON.stringify(this.state.currentPos, null, 2)}</pre>
</Popup>
</Marker>}
</Map>
</div>
)
}
}
Explanation:
currentPos state is used to keep marker position
event.latLng property of Map.onClick event handler returns mouse event location
Here is a demo for your reference
What did you try to achieve that?
This will be the start:
Use the click (see https://leafletjs.com/reference-1.4.0.html#map-click) event from the LeafletMap component and call your function, like:
<LeafletMap
center={[35.755229,51.304470]}
zoom={16}
maxZoom={20}
attributionControl={true}
zoomControl={true}
doubleClickZoom={true}
scrollWheelZoom={true}
dragging={true}
animate={true}
easeLinearity={0.35}
onclick={this.handleClick}>
>
...
</LeafletMap>
In your handleClick function you get the information of lat and lng like this:
handleClick = (e) => {
const { lat, lng } = e.latlng;
console.log(lat, lng);
}
From here on, you can create your marker / popup with the information you were looking for.
Additional hint: Please make sure your code is wrapped in correctly in your post..
If you work with react-leaflet version 3.x this does not work. In this case, use the useMapEvents hook in a dummy component that you add to the map. For example, if you want to console.log the clicked position:
const LocationFinderDummy = () => {
const map = useMapEvents({
click(e) {
console.log(e.latlng);
},
});
return null;
};
Then use the LocationFinderDummy in the map as follows:
<MapContainer
center={[0, 0]}
zoom={6}>
<LocationFinderDummy />
</MapContainer>

Super expression must either be null or a function, not undefined - react-google-maps

Whenever I am importing this #react-google-maps library I am getting this error. Can anyone help me with this issue?
This is my component -
const {withScriptjs, withGoogleMap, GoogleMap, Marker} = require('react-google-maps');
const VenueMap = React.createClass({
getInitialState() {
const {eventData} = this.props;
const stateObj = {
position: {
lat: eventData.venue.latitude,
lng: eventData.venue.longitude,
},
defaultZoom: 17
};
return stateObj;
},
render: function () {
const {state} = this;
const MapComponent = compose(
withProps({
googleMapURL: GOOGLE_MAP.mapURL,
loadingElement: <div style={{height: `100%`}}/>,
containerElement: <div style={{height: `300px`, marginBottom: `30px`}}/>,
mapElement: <div style={{height: `100%`}}/>
}),
withScriptjs, withGoogleMap
)(props => (
<GoogleMap
defaultZoom={state.defaultZoom}
defaultCenter={state.position}>
{props.isMarkerShown && <Marker position={state.position}/>}
</GoogleMap>
));
return (
<div id="venuelocation" className="contents-wrapper">
<div className="orgname" style={{paddingBottom: '20px'}}>Venue Location</div>
<MapComponent isMarkerShown={true}/>
</div>
);
}
});
I am using react 16.3.2 reactjs version.
two things.
1- it is weird for you to use React.CreateClass with React ^16 because it was removed according to this article:
React Class being Removed
2 - I tried your code on a sandbox using the extend ES6 functionality and it works for me, actually I had to hardcode some stuff but everything is loading, although I don't have keys to open the maps api, check it out here.
https://codesandbox.io/s/rjrzvlw36o
My guesses: I think you are missing a super() in some place, next time it will be helpful to also add the stack of the error, so we can see if something in particular is throwing the error.

Resources