反应传单v4设置和改变标记点击



我无法在单击时设置和更改标记。

我从浏览器中获取用户的位置,并用这些坐标将地图居中。当我运行console.log(coords(时,我可以看到浏览器获取的坐标,但当我使用[formValues.cords[0],formValues.cords[1]]将标记设置为LatLngExpression时,它不起作用。当我点击地图时,它也不会改变坐标。我做错了什么,但我还没弄清楚在哪里。

我看到的另一件事是,whenCreated属性已从react传单v4:中删除

"从MapContainer组件中删除了whenCreated属性(可以使用ref回调(">

但我不知道如何在这种情况下使用这个ref回调。

有人能帮我吗?这是地图绘制部分的代码:

import {
Button,
ButtonContainer,
CategoryBox,
CategoryContainer,
CategoryImage,
Container,
Form,
FormTitle,
MapContainer,
Section,
} from "./styles";
import Input from "../../components/Input";
import { useState } from "react";
import { LatLngExpression, LeafletMouseEvent } from "leaflet";
import { TileLayer, Marker } from "react-leaflet";
import { categories } from "./categories";
import useGetLocation from "../../hooks/useGetLocation";
import { toast } from "react-toastify";
import { useNavigate } from "react-router-dom";
export default function New() {
const navigate = useNavigate();
const [formValues, setFormValues] = useState({
name: "",
description: "",
contact: "",
category: "",
coords: [0, 0],
});
const { coords } = useGetLocation();
console.log(coords);
async function onSubmit() {
const request = await fetch("http://localhost:5000/store", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
...formValues,
latitude: formValues.coords[0],
longitude: formValues.coords[1],
}),
});
if (request.ok) {
toast("Estabelecimento gravado com sucesso!", {
type: "success",
autoClose: 2000,
onClose: () => navigate("/"),
});
}
}
if (!coords) {
return <h1>Obtendo localização...</h1>;
}
return (
<Container>
<Form
onSubmit={(ev) => {
ev.preventDefault();
onSubmit();
}}
>
<FormTitle>Cadastro do comércio local</FormTitle>
<Section>Dados</Section>
<Input
label="Nome do local"
name="name"
value={formValues.name}
onChange={setFormValues}
/>
<Input
label="Descrição"
name="description"
value={formValues.description}
onChange={setFormValues}
/>
<Input
label="Contato"
name="contact"
value={formValues.contact}
onChange={setFormValues}
/>
<Section>Endereço</Section>
<MapContainer
center={
{
lat: coords[0],
lng: coords[1],
} as LatLngExpression
}
zoom={13}
whenCreated={(map) => {
map.addEventListener("click", (event: LeafletMouseEvent) => {
setFormValues((prev) => ({
...prev,
coords: [event.latlng.lat, event.latlng.lng],
}));
});
}}
>
<TileLayer
attribution='&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
/>
<Marker
position={
[formValues.coords[0], formValues.coords[1]] as LatLngExpression
}
/>
</MapContainer>
<Section>Categoria</Section>
<CategoryContainer>
{categories.map((category) => (
<CategoryBox
key={category.key}
onClick={() => {
setFormValues((prev) => ({ ...prev, category: category.key }));
}}
isActive={formValues.category === category.key}
>
<CategoryImage src={category.url} />
{category.label}
</CategoryBox>
))}
</CategoryContainer>
<ButtonContainer>
<Button type="submit">Salvar</Button>
</ButtonContainer>
</Form>
</Container>
);
}
是的,所以WhenCreated不再是道具了。我认为有一种更简单的方法不需要干扰refs。首先你需要做的是移动你的地图容器,使其成为包装器,然后你可以使用这样的东西使标记移动到你点击的任何地方:
function MovingMarker() {
const [position, setPosition] = useState(center)
const markerRef = useRef(null)
const map = useMapEvent('click', (e) => {
console.log("click")
setPosition(e.latlng)
})

return (
<Marker
position={position}
ref={markerRef}>
</Marker>

)
}
render(
<MapContainer center={center} zoom={13} scrollWheelZoom={false}>
<TileLayer
attribution='&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
/>
<MovingMarker />

</MapContainer>
)

您可以在上运行此演示https://react-leaflet.js.org/docs/api-map/如果你想在生活环境中玩它。如果您需要将标记的坐标向上拉到MapContainer之外,那么我建议在MovingMarker组件中添加一个类似onChange={(e)=>{setGlobalMarkerPos(e)}}的道具。这样,任何更改都将传播到组件堆栈中。或者您可以使用上下文管理器。

另一种解决方案是获取地图参考:

function RealMapContainer() {
const [position, setPosition] = useState(center)
const [listenerSetup, setListenerSetup] = useState(null)
const mapRef = useRef(null)
if(mapRef.current && !listenerSetup){
console.log(mapRef);
mapRef.current.on('click', (e)=>{
setPosition(e.latlng) 
})
setListenerSetup(true)
}
//if we still haven't setup the listener, 
//then setListenerSetup(false) is just a way to make this
//component keep rendering over and over until the reference 
//is finally defined and the listener can be set up
else if(!listenerSetup){
setTimeout(()=>{ 
setListenerSetup(false)
}, 100)
}

return (
<MapContainer center={center} zoom={13} scrollWheelZoom={false} ref={mapRef}>
<TileLayer
attribution='&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
/>
<Marker position={position}/>

</MapContainer>

)
}

然后,您将有一个对MapObject的实际引用,并以普通传单文档指定的所有方式使用它。

我添加了一个用于移动标记位置的点击处理程序。listenerSetup的整个过程只是一种愚蠢的方法,让它继续重新渲染,直到找到对贴图对象的引用。我几乎只使用基于类的React,所以我相信有更好的方法,但它有效。如果有人读到这篇文章知道更好的方法,请留言告诉我,这样我就可以更新了。

最新更新