I'm playing around with Gatsby, Contentful and Google Maps. Here's the page that I'm working on:
import React, { useState } from 'react'
import Layout from '../components/Layout'
import { withGoogleMap, withScriptjs } from 'react-google-maps'
import Map from '../components/Map'
import 'react-responsive-modal/styles.css';
import { Modal } from 'react-responsive-modal';
const MapComponent = withScriptjs(withGoogleMap(Map));
export default function IndexPage() {
const [modal, setmodal] = useState(false)
return (
<Layout>
<div style={{ width: "100%", height: "100vh" }} >
<MapComponent
googleMapURL={`https://maps.googleapis.com/maps/api/js?v=3.exp&libraries=geometry,drawing,places&key=${"AIzaSyAGJcMjH34D2QWQpOKhOulJGfZ9kXVQuj8"}`}
loadingElement={<div style={{ height: `100%` }} />}
containerElement={<div style={{ height: `100%` }} />}
mapElement={<div style={{ height: `100%` }} />}
setmodal={setmodal}
/>
</div>
<Modal
open={modal}
onClose={() => setmodal(false)}
>
<h1>Contentful Content Here</h1>
</Modal>
</Layout>
)
}
I extended the page and created a./components/Map component to it. In the Map component I'm querying Contentful data.
Like this:
import React, { useState } from 'react'
import { GoogleMap, Marker, InfoWindow } from 'react-google-maps'
import { useStaticQuery, graphql } from "gatsby"
const Map = (props) => {
const data = useStaticQuery(graphql`
{
allContentfulLocations {
nodes {
id
name
location {
lat
lon
}
}
}
}
`)
const {
allContentfulLocations: { nodes: locations },
} = data
const [infoWindow, setInfoWindow] = useState(null)
return (
<GoogleMap
defaultZoom={12}
defaultCenter={{
lat: 14.05223,
lng: 218.2437
}}
>
{locations.map(({ location }) => {
console.log(location);
return (
<Marker
onMouseOver={() => {
setInfoWindow(true)
}}
onClick={() => {
props.setmodal(true)
}}
position={{
lat: location.lat,
lng: location.lon
}}
/>
)
})}
</GoogleMap>
)
}
export default Map;
Now, I want to use the Contentful data inside the component on my page too. How can I access the Contentful data from the component and implement it on my page?
My Approach was to use useState with data,setData like this on my page:
import React, { useState } from 'react'
import Layout from '../components/Layout'
import { withGoogleMap, withScriptjs } from 'react-google-maps'
import Map from '../components/Map'
import 'react-responsive-modal/styles.css';
import { Modal } from 'react-responsive-modal';
const MapComponent = withScriptjs(withGoogleMap(Map));
export default function IndexPage() {
const [modal, setmodal] = useState(false)
const [data, setData] = (null)
return (
<Layout>
<div style={{ width: "100%", height: "100vh" }} >
<MapComponent
googleMapURL={`https://maps.googleapis.com/maps/api/js?v=3.exp&libraries=geometry,drawing,places&key=${"AIzaSyAGJcMjH34D2QWQpOKhOulJGfZ9kXVQuj8"}`}
loadingElement={<div style={{ height: `100%` }} />}
containerElement={<div style={{ height: `100%` }} />}
mapElement={<div style={{ height: `100%` }} />}
setmodal={setmodal}
setData={setData}
/>
</div>
<Modal
open={modal}
onClose={() => setmodal(false)}
>
<h1>{data.locations.name}</h1>
</Modal>
</Layout>
)
}
And in the Map component, inside the Marker component I've added a props.setData for the to access the data.
import React, { useState } from 'react'
import { GoogleMap, Marker, InfoWindow } from 'react-google-maps'
import { useStaticQuery, graphql } from "gatsby"
const Map = (props) => {
const data = useStaticQuery(graphql`
{
allContentfulLocations {
nodes {
id
name
location {
lat
lon
}
}
}
}
`)
const {
allContentfulLocations: { nodes: locations },
} = data
const [infoWindow, setInfoWindow] = useState(null)
return (
<GoogleMap
defaultZoom={12}
defaultCenter={{
lat: 14.05223,
lng: 218.2437
}}
>
{locations.map(({ location }) => {
console.log(location);
return (
<Marker
onMouseOver={() => {
setInfoWindow(true)
}}
onClick={() => {
props.setmodal(true)
props.setData(location)
}}
position={{
lat: location.lat,
lng: location.lon
}}
/>
)
})}
</GoogleMap>
)
}
export default Map;
I'm stuck now. Getting an error saying that allContentfulLocations is undefined and I'm not receiving the data into my page. Can someone help me to get it right?
In your IndexPage
, your state is held by data
, not by setData
. setData
is just a setter function that sets the state within the provided data but your information is inside data
, in addition, the setter doesn't accept any parameter by default so won't be able to use props.setData(location)
. Change it to:
import React, { useState } from 'react'
import Layout from '../components/Layout'
import { withGoogleMap, withScriptjs } from 'react-google-maps'
import Map from '../components/Map'
import 'react-responsive-modal/styles.css';
import { Modal } from 'react-responsive-modal';
const MapComponent = withScriptjs(withGoogleMap(Map));
export default function IndexPage() {
const [modal, setmodal] = useState(false)
const [data, setData] = useState(null)
const setYourData= data => setData(data);
return (
<Layout>
<div style={{ width: "100%", height: "100vh" }} >
<MapComponent
googleMapURL={`https://maps.googleapis.com/maps/api/js?v=3.exp&libraries=geometry,drawing,places&key=${"AIzaSyAGJcMjH34D2QWQpOKhOulJGfZ9kXVQuj8"}`}
loadingElement={<div style={{ height: `100%` }} />}
containerElement={<div style={{ height: `100%` }} />}
mapElement={<div style={{ height: `100%` }} />}
setmodal={setmodal}
setYourData={setYourData}
data={data}
/>
</div>
<Modal
open={modal}
onClose={() => setmodal(false)}
>
{ data && <h1>{data.location.name}</h1>}
</Modal>
</Layout>
)
}
Now, you are passing a function ( setYourData
) that is accepting a parameter ( data
) and sets the state accordingly, so your props.setData(location). Will become:
props.setYourData(location);
This value needs to be passed again downwards to your map component using data={data}
(I would strongly suggest a new naming since it's a bit repetitive and may lead to some misunderstandings).
Note also the { data && <h1>{data.locations.name}</h1>}
control. Initially, you've set to null
the state, so your code can't reach data.locations
.
Once the data
is passed to the map component, you can play whatever you want with now new brand location
, stored in data ( props.data
). Your map component should look like this:
import React, { useState } from 'react'
import { GoogleMap, Marker, InfoWindow } from 'react-google-maps'
import { useStaticQuery, graphql } from "gatsby"
const Map = (props) => {
console.log(props.data) // here you have your new data/location
const data = useStaticQuery(graphql`
{
allContentfulLocations {
nodes {
id
name
location {
lat
lon
}
}
}
}
`)
const {
allContentfulLocations: { nodes: locations },
} = data
const [infoWindow, setInfoWindow] = useState(null)
return (
<GoogleMap
defaultZoom={12}
defaultCenter={{
lat: 14.05223,
lng: 218.2437
}}
>
{locations.map(({ location }) => {
console.log(location);
return (
<Marker
onMouseOver={() => {
setInfoWindow(true)
}}
onClick={() => {
props.setmodal(true)
props.setYourData(location)
}}
position={{
lat: location.lat,
lng: location.lon
}}
/>
)
})}
</GoogleMap>
)
}
export default Map;
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.