#javascript #reactjs #gatsby
#javascript #reactjs #gatsby
Вопрос:
Я играю с Gatsby, Contentful и Google Maps. Вот страница, над которой я работаю:
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.expamp;libraries=geometry,drawing,placesamp;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>
)
}
Я расширил страницу и создал для нее компонент ./components/Map . В компоненте Map я запрашиваю данные содержимого.
Вот так:
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;
Теперь я хочу использовать данные содержимого внутри компонента и на своей странице. Как я могу получить доступ к содержательным данным из компонента и реализовать их на своей странице?
Мой подход заключался в использовании useState с данными, такими как setData на моей странице:
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.expamp;libraries=geometry,drawing,placesamp;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>
)
}
И в компоненте Map, внутри компонента Marker я добавил props.setData для доступа к данным.
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;
Теперь я застрял. Получаю сообщение об ошибке, в котором говорится, что значение allContentfulLocations не определено, и я не получаю данные на свою страницу. Может кто-нибудь помочь мне сделать это правильно?
Ответ №1:
В вашем IndexPage
случае ваше состояние удерживается data
, а не by setData
. setData
это просто функция установки, которая устанавливает состояние в предоставленных данных, но ваша информация находится внутри data
, кроме того, установщик не принимает никаких параметров по умолчанию, поэтому не сможет использовать props.setData(location)
. Измените его на:
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.expamp;libraries=geometry,drawing,placesamp;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 amp;amp; <h1>{data.location.name}</h1>}
</Modal>
</Layout>
)
}
Теперь вы передаете функцию ( setYourData
), которая принимает параметр ( data
) и соответствующим образом устанавливает состояние, поэтому ваш props.setData(местоположение) . Станет:
props.setYourData(location);
Это значение необходимо снова передать вашему компоненту карты, используя data={data}
(я бы настоятельно рекомендовал новое название, поскольку оно немного повторяющееся и может привести к некоторым недоразумениям).
Обратите внимание также на { data amp;amp; <h1>{data.locations.name}</h1>}
элемент управления. Изначально вы установили null
состояние, поэтому ваш код не может достичь data.locations
.
Как только data
данные передаются компоненту map, вы можете воспроизводить все, что захотите, с новым брендом location
, хранящимся в data ( props.data
) . Ваш компонент карты должен выглядеть следующим образом:
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;
Комментарии:
1. Я пробовал это, но теперь получаю следующее сообщение об ошибке: TypeError: не удается прочитать свойство ‘0’ из null . Могу ли я запросить данные на странице, используя <h1>{data.location.name }</h1> ?
2. В
IndexPage
должен бытьdata.name
directly (console.log(data)
), чтобы знать, что внутри. Для доступа кlat
иlong
, должно бытьdata.location.lat
. Если вы хотите использовать его в компоненте map, то же самое с помощью префиксаprop
(т.е.:props.data.name
, и т.д.)3. Я реализовал это, но я все еще получаю одно и то же сообщение об ошибке, поступающее из IndexPage. Ошибка типа: не удается прочитать свойство ‘0’ из null
4. Добавьте элемент управления в
<h1>{data.locations.name}</h1>
. Поскольку вы пытаетесь получить доступ к нулевому свойству. Сделайте что-то вроде: {data amp;amp; <h1>{data.locations.name }</h1>}5. Я пробовал это. К сожалению, я все еще получаю сообщение об ошибке. Должно быть что-то :/