change cursor to pointer google-maps-react - reactjs

I am using google-maps-react. By default, when I put the mouse on map, it shows a hand cursor. I would like to set a normal pointer when person hover on map, and only when start dragging, the cursor become again a hand cursor.
I was trying to set draggableCursos prop in many ways, but I didnt get what I wanted.
Thank You for help in advance.

It appears the current version (2.0.2) of google-maps-react package published in npm does not support to specify a few properties including MapOptions.draggableCursor and MapOptions.draggingCursor via Map component. In such a cases those properties could be specified via native map object. The following example demonstrates it
class MapContainer extends React.Component {
constructor(props) {
super(props);
this.handleMapReady = this.handleMapReady.bind(this);
}
handleMapReady(mapProps,map) {
map.setOptions({
draggableCursor: "default",
draggingCursor: "pointer"
});
}
render() {
return (
<div className="map-container">
<Map
google={this.props.google}
className={"map"}
zoom={this.props.zoom}
initialCenter={this.props.center}
onReady={this.handleMapReady}
/>
</div>
);
}
}
Here is a demo

You can add a custom className to the map and attach an event that will change the pointer-events CSS property on the map.

Related

Not able to change center dynamically in React-Leaflet v.3.x

i am working on this React-Leaflet Map. I want to update value of "center" prop of MapContainer based on input provided by User, but it is not working.
I know, methods like flyTo(), panTo() are used in such situations but i don't know where/how to apply them... Please help.
Here's the link to codesandbox https://codesandbox.io/s/stoic-lamport-kk8mj?file=/src/App.js
From the official docs:
Except for its children, MapContainer props are immutable: changing
them after they have been set a first time will have no effect on the
Map instance or its container.
As a result, when you change center variable the center does not change. Create a function that changes the map center upon dropdown selection change
function SetViewOnClick({ coords }) {
const map = useMap();
map.setView(coords, map.getZoom());
return null;
}
Include it on MapComp
function MapComp({ coords }) {
return (
<MapContainer
classsName="map"
center={coords}
zoom={4}
scrollWheelZoom={false}
>
...
<SetViewOnClick coords={coords} />
</MapContainer>
);
}
Demo
Note that the coordinates for USA and Canada are not correct so I changed them. They should be
{
USA: [39.7837304, -100.4458825]
},
{
Canada: [61.0666922, -107.9917071]
},
and moreover the countries variable does not have to be a state variable as you do not change it. It should be a constant.
Also there is an error in the console because you are using an array on the select element which expects multi selection when using arrays but obviously you do not want that.
Last but not least you should handle the none selection somehow because an error occurs when selecting none.

Set z-index of OverlayView in react-google-maps

I am using react-google-maps and I want to accomplish something similar to Airbnb where when you hover over a search result and then a "marker" (aka OverlayView) is highlighted on the map. But the issue I am trying to solve is if an OverlayView is underneath another OverlayView, I want to bring that "active" OverlayView to the top (like by adjusting the z-index). The map on Airbnb does this very thing, which is when you hover over the search result and inspect the marker the z-index is altered to be 9001 to ensure it is brought to the front of all other markers.
There are a few issues related to this from years ago that have not received any movement:
tomchentw/react-google-maps#199
tomchentw/react-google-maps#93
In issue #199 it was mentioned you could hack around it with this.refs.childDiv.parentNode and setting z-index on that, but in React v16 this.refs is no longer a thing from what I can tell (it was deprecated). The original commenter attached a jsfiddle with the code sample which was:
class OverlayViewExample extends React.Component {
render () {
const pos = {lat: -34.397, lng: 150.644};
const mapPane = OverlayView.OVERLAY_MOUSE_TARGET;
const getOffset = this.getPixelPositionOffset.bind(this);
return (
<GoogleMap
defaultZoom={8}
defaultCenter={pos}
>
<OverlayView
position={pos}
mapPaneName={mapPane}
getPixelPositionOffset={getOffset}
>
<div style={{zIndex: 2}} className="overlay" ref="childDiv">This should be in front</div>
</OverlayView>
<OverlayView
position={pos}
mapPaneName={mapPane}
getPixelPositionOffset={getOffset}
>
<div style={{zIndex: 1}} className="overlay">Another overlay should be in front of me</div>
</OverlayView>
</GoogleMap>
);
}
getPixelPositionOffset (width, height) {
// this.refs is an empty object when I tried this :(
if (this.refs.childDiv) {
this.refs.childDiv.parentNode.style.zIndex = 2;
}
return { x: -(width / 2), y: -(height / 2) };
}
}
When I tried this workaround, this.refs was an empty object and therefore I could not alter the underlying zIndex of that node.
Is there another way to ensure when two OverlayViews are near each other that I can bring the one in the background to the foreground?
The answer for this was actually in my question (I should've tested the example code from Github)...
On this line: <div style={{zIndex: 2}} className="overlay" ref="childDiv">This should be in front</div> the zIndex was actually doing what I wanted (it would bring forward whichever element I wanted in the foreground).
So within each OverlayView, just apply a z-index to the first child element and that will effect the ordering of each OverlayView.

React onTouchStart not firing

I am trying to implement a swipe feature in ReactJS, but before I even really dive in, I cannot seem to get the onTouchStart event listener to work. I have looked online but most answers are outdated, or do not address my question directly. This link is where I got the most information thus far, but it still falls short of my question and some of the answers are outdated. What's the proper way of binding touchstart on React JS?
I went down to creating the simplest form of the functionality and included that code below. I was trying to console.log when onTouchStart={this.swiped}> occurs. On a side note, if I change the listener to onClick onClick={this.swiped}>, this works immediately.
class App extends React.Component {
contructor() {
super();
this.swiped = this.swiped.bind(this);
}
swiped() {
console.log("Swiped")
}
render() {
return (
<div>
<div
className='swipe-card'
onTouchStart={this.swiped}>Swipe Me
</div>
</div>
)
}
}
Also, I have added the CSS style cursor: pointer to the element. I also tried adding
componentWillMount: function(){
React.initializeTouchEvents(true);
}
But according to the React blogs, React.initializeTouchEvents is no longer required.
This seems so trivial and something that should be really simple to implement. What am I missing? My goal is to implement this without an external library. Here is a link to Codepen where I was trying to implement this.
https://codepen.io/jorgeh84/pen/mMdBZg
This works for me. Maybe the issue is that you're not testing it on a real device?
class App extends React.Component {
contructor() {
super();
}
swiped = () => {
console.log("Swiped")
}
render() {
return (
<div>
<div className='swipe-card' onTouchStart={this.swiped}>Swipe Me</div>
</div>
)
}
}
ReactDOM.render(<App />, document.getElementById('App'))
I realized that Daniel was onto something. So I do not need to be testing on an actual device, however, when using Chrome, you will need to use their device toolbar to simulate a mobile device for this to work.

How do properly use Onsen's Navigator in React?

I'm trying to implement a simple Onsen Navigator in React.
So far I'm receiving an error 'route is not defined' and I was looking through the examples & docs but I only saw the initialRoute prop was provided, how & where does the route prop generated or something? Cause it seems like its not specified.
Here is my the code of my component:
import React, {PropTypes} from 'react';
import ons from 'onsenui';
import * as Ons from 'react-onsenui';
class SignUp extends React.Component {
constructor(props) {
super(props);
this.state = {
index : 0
};
this.renderPage = this.renderPage.bind(this);
this.pushPage = this.pushPage.bind(this);
}
pushPage(navigator) {
navigator.pushPage({
title: `Another page ${this.state.index}`,
hasBackButton: true
});
this.setState({index: this.state.index++});
}
renderPage(route, navigator) {
return (
<Ons.Page key={route.title}>
<section style={{margin: '16px', textAlign: 'center'}}>
<Ons.Button onClick={this.pushPage}>
Push Page
</Ons.Button>
</section>
</Ons.Page>
);
}
render() {
return (
<Ons.Page key={route.title}>
<Ons.Navigator
renderPage={this.renderPage}
initialRoute={{
title: 'First page',
hasBackButton: false
}}
/>
</Ons.Page>
);
}
};
SignUp.propTypes = {
'data-pageName': PropTypes.string.isRequired
};
export default SignUp;
Is this the right syntax in ES6? Have I missed something?
When using Ons.Navigator in react the two required properties are:
initialRoute - it should be an object.
renderPage - method which receives 2 arguments - route and navigator. The route should be an object similar to the initialRoute one. You provide that object when you are calling pushPage and similar methods.
It seems that you already know these 2, but there still 2 other things which you need to be careful about. They are not directly onsen related, but come up a lot when using react in general.
Whenever you have a list of dom elements (for example an array of Ons.Page tags) each of those should have a unique key property.
Whenever you use a method you need to make sure you are binding it if you need some extra arguments.
It seems you also know these two. So the only thing left is to make sure you follow them.
Your syntax is correct - the only thing missing is the route variable in SignUp.render. Maybe you originally copied the renderPage method and that is how you have a leftover Ons.Page.
If you're not putting the SignUp component inside some other navigator, tabbar or splitter then you don't actually need the Ons.Page in its render method. Those are the only cases when they are needed. If you it happens to have one of those components as a parent then you can just specify the key.
PS: I think there should be a React Component Inspector (something like this) which you can install - then I think you may be able to see the place where the error occurs. I think if you knew on which line the problem was you would have been able to solve it. :)
For me, with the object I was passing to initialRoute(), it needed a props property, which itself was an object with a key property. See the before and after below.
Before fixing
render() {
return (
<Navigator
initialRoute={{component: DataEntryPage}}
renderPage={this.renderPage}
/>
);
}
}
This was causing the following console warning:
Warning: Each child in an array or iterator should have a unique "key" prop.
Check the render method of `Navigator`.
After fixing
render() {
return (
<Navigator
initialRoute={{component: DataEntryPage, props: {key: 'DataEntryPage'}}}
renderPage={this.renderPage}
/>
);
}
}
Notice that the difference I needed to make was the addition of , props: {key: 'DataEntryPage'}.
Feel free to check out this medium article for more information.

In componentDidUpdate refs is undefined

I want to use Chart.js on my website. As you can see title, I'm using React.js. To use Chart.js, I need the canvas and context like this:
let context = document.getElementById('canvas').getContext('2d');
let chart = new Chart(context, ...);
so I design the component like this:
export function updateChart() {
let context = this.refs.chart.getContext('2d');
let chart = new Chart(context ,... );
...
}
export default class GraphChart extends React.Component {
constructor() {
super();
updateChart = updateChart.bind(this);
}
componentDidMount() {
updateChart();
}
render() {
return <canvas ref="chart" className="chart"></canvas>;
}
}
as you can see, I exported two things, update chart function and GraphChart class. Both will using in parent component like this:
import { updateChart } from './GraphChart';
import GraphChart from './GraphChart';
class Graph extends React.Component {
...
someKindOfAction() {
// update chart from here!
updateChart();
}
render() {
return (
<div>
<SomeOtherComponents />
<GraphChart />
</div>
);
}
}
then Parent class using exported updateChart function to update chart directly. It was working, but only first time. After unmount and mount the GraphChart component, it's refs are just empty.
Why refs is empty? And If I did wrong way, how can I get canvas context for initialize Chart.js?
Object refs is undefined, because this is not what you think it is. Try logging it.
The function you’re exporting is not bound to this of your component. Or perhaps it is, but to the last created instance of your component. You can never be sure that’s the mounted instance. And even if you are, you can not use multiple instances at the same time. So, I would dismiss this approach entirely.
Other than that, providing the function to alter some component’s state is exactly the opposite of what’s React is trying to accomplish. The very basic idea is that the component should know to render itself given some properties.
The problem you are trying to solve lies in the nature of Canvas API, which is procedural. Your goal is to bridge the gap between declarative (React) and procedural (Canvas) code.
There are some libraries which do exactly that. Have you tried react-chartjs? https://github.com/reactjs/react-chartjs
Anyways, if you’re wondering how the hell should you implement it the “React way”, the key is to declare properties your component handles (not necessarily, but preferably), and then to use component lifecycle methods (e.g. componentWillReceiveProps and others) to detect when properties change and act accordingly (perform changes to the canvas).
Hope this helps! Good luck!

Resources