如何解决react-map-gl 并使用 useContext 和/或 useState 从另一个组件更改视口
我最近似乎什么都不明白,并且很难通过 React/Nextjs 和 react-map-gl 掌握 useContext 和/或 useState。
基本上,我有两个组成部分。使用 Formik 和来自 react-map-gl 的地图的搜索框。我想要做的是能够让 Formik 的变量之一能够更改 react-map-gl 上的视口,以便将地图的视口重定向到新坐标。我尝试研究和阅读我可以做些什么来完成这项工作,但我无法理解。我相信它必须是一些简单的东西,我太新而无法理解。每次我认为我拥有它时,我都会收到一条错误消息,说我实际上无法做到这一点。
作为参考,这是我当前使用 useState 的代码。每当我尝试使用它并点击提交按钮时,我都会收到“1 of 1 unhandled error” 未处理的运行时错误
TypeError: setViewport 不是函数 "
这似乎没有任何意义:(。其他时候,当我可以让它工作时,我必须单击提交按钮两次才能让表单注册新的 setViewport。我做错了什么?谢谢你的帮助!
index.js
import { Grid } from '@material-ui/core';
import { useState } from 'react';
import SearchBox from '../components/searchbox';
import {
getAllCampgrounds,getAllCities,getCampgroundsByCity,} from '../lib/api';
import Map from '../components/map';
export default function CampList({
graphCampgrounds,cities,campgroundsbycity,}) {
const [viewport,setViewport] = useState({
height: '100vh',latitude: 44.0456,longitude: -71.6706,width: '100vw',zoom: 8,});
return (
<Grid container spacing={3}>
<Grid item xs={12} sm={5} md={3} lg={2}>
<SearchBox
graphCampgrounds={graphCampgrounds}
cities={cities}
campgroundsbycity={campgroundsbycity}
setViewport={() => setViewport}
/>
</Grid>
<Grid item xs={12} sm={7} md={9} lg={10}>
<Map
campgrounds={graphCampgrounds}
viewport={viewport}
setViewport={() => setViewport}
/>
<pre style={{ fontSize: '2.5rem' }}>{}</pre>
</Grid>
</Grid>
);
}
我省略了我的 getServerSideProps 区域。这是我的 Searchbox.js:
import Link from 'next/link';
import { Form,Formik,Field,useFormik } from 'formik';
import {
Paper,Grid,FormControl,InputLabel,Select,MenuItem,Button,} from '@material-ui/core';
import { makeStyles } from '@material-ui/core/styles';
import { useRouter } from 'next/router';
const useStyles = makeStyles(theme => ({
paper: {
margin: 'auto',maxWidth: 500,padding: theme.spacing(3),},}));
export default function SearchBox({
graphCampgrounds,viewport,setViewport,}) {
const router = useRouter();
const { query } = router;
const handleSubmit = async values => {
setViewport({
...viewport,latitude: campgroundsbycity
? parseFloat(campgroundsbycity.nodes[0].acfDetails.latitude.toFixed(4))
: 44.43,longitude: campgroundsbycity
? Math.abs(
parseFloat(campgroundsbycity.nodes[0].acfDetails.longitude.toFixed(4))
) * -1
: -72.352,zoom: 11,});
router.push(
{
pathname: '/camps',query: { ...values,page: 1 },undefined,{ shallow: true }
);
};
const classes = useStyles();
const smValue = singleColumn ? 12 : 6;
const initialValues = {
city: query.city || 'all'
};
return (
<Formik initialValues={initialValues} onSubmit={handleSubmit}>
{({ values,submitForm }) => (
<Form>
<Paper className={classes.paper} elevation={5}>
<Grid container spacing={3}>
<Grid item xs={12} sm={smValue}>
<FormControl fullWidth variant="outlined">
<InputLabel id="search-cities">City</InputLabel>
<Field
name="city"
as={Select}
labelId="search-cities"
label="Cities"
>
<MenuItem value="all">
<em>All</em>
</MenuItem>
{cities.nodes.map(town => {
return (
<MenuItem
key={town.acfDetails.city}
value={town.acfDetails.city}
>
{town.acfDetails.city}
</MenuItem>
);
})}
</Field>
</FormControl>
</Grid>
<Grid item xs={12}>
<Button
color="primary"
variant="outlined"
type="button"
fullWidth
onClick={submitForm}
>
Search Campgrounds
</Button>
</Grid>
</Grid>
</Paper>
</Form>
)}
</Formik>
);
}
这是我的地图组件:
import { useContext,useMemo } from 'react';
import ReactMapGL,{ Marker,MapContext } from 'react-map-gl';
import { ViewportContext } from '../lib/state';
export default function Map({ campgrounds,setViewport }) {
const markers = campgrounds.map(({ node }) => {
console.log(node.acfDetails);
return (
<Marker
key={node.title}
longitude={
Math.abs(parseFloat(node.acfDetails.longitude.toFixed(4))) * -1
}
latitude={parseFloat(node.acfDetails.latitude.toFixed(4))}
>
<img src="pin.png" alt={node.title} />
</Marker>
);
});
return (
<ReactMapGL
mapboxApiAccessToken={process.env.NEXT_PUBLIC_MAPBOX_KEY}
mapStyle="mapbox://styles/mapbox/outdoors-v11"
{...viewport}
onViewportChange={nextViewport => setViewport(nextViewport)}
>
{markers}
</ReactMapGL>
);
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。