네이버 지도에 동 marker를 map함수로 나타냈다.
각각의 marker를 클릭하면 해당 marker에 해당하는 circle이 나타난다.
하지만 marker 자체를 map을 돌렸기 때문에 1번 marker를 클릭하면 1,2,3 marker 각각에 대한 circle을 모두 그린다.
나는 1번 marker에 해당하는 circle만 띄우고 싶다.
문제의 모든 서클 나타내기
const [openCircle, setOpenCircle] = useState(false);
//서클이 나타났다 꺼졌다를 모달을 위한 state
const [selectedMarkerId, setSelectedMarkerId] = useState(0);
//각 Marker의 id 값을 비교하기 위한 state
//초기값이 0인 이유는 id 값이 0인 Marker가 없기 때문
const handleClickMarker = marker => {
setSelectedMarkerId(marker.id);
setOpenCircle(!openCircle);
};
//Marker를 클릭하면 해당 Marker의 id값이 selectedMarkedId state에 할당된다.
return (
//storeMarker는 Marker와 Circle에 대한 모든 데이터를 가지고 있다.
{storeMarker.map(data => (
<div key={data.id}>
<Marker
position={
new navermaps.LatLng(data.x_coordinate, data.y_coordinate)
}
icon={{
content: `<div class="markerBoxStore">
<h1 class="markerCountTextStore">아이콘</h1>
<p class="markerTextStore">${data.name}</p>
</div>`,
}}
title={data.name}
onClick={() => handleClickMarker(data)}
/>
{selectedMarkerId === data.id && openCircle && (
<Circle
center={[data.y_coordinate, data.x_coordinate]}
radius={1000}
fillOpacity={0.5}
fillColor="#8CD790"
strokeWeight={2}
strokeColor="#5CAB7D"
strokeStyle="dashed"
clickable={true}
/>
)}
</div>
))}
)
}
handleClickMarker
함수에 의해 Marker가 클릭되면 data라는 인수가 marker로 전달된다.
1번 매장의 marker를 클릭하면 해당 매장의 marker id 값이 selectedMarkerId에 할당된다.
Circle 컴포넌트는 selectedMarkerId와 marker의 id가 일치하면 지도에 그려진다.
1번 매장 marker의 id 값이 1
클릭하면 해당 id 값이 selectedMarkerId
에 저장 selectedMarkerId = 1
현재 <Marker/>
와 <Circle/>
에 뿌려지는 데이터는 1번 매장
따라서 selectedMarkerId === data.id
는 true
marker에는 고유의 id 값이 있다.
내가 클릭한 marker의 id 값과 selectMarker의 id가 같다면 circle을 보여줘라
여기서 circle에는 id 값이 없다. 그럼 어떻게 알고 1번 marker에 해당하는 circle이 나타날까
일단 map 함수가 돌아갈때 먼저 첫번째 배열의 요소가 들어가지?
데이터는 1번 marker에 해당하는 데이터가 들어가지!
data.x_coordinate, data.y_coordinate
여기에도 1번 marker에 해당하는 좌표가 들어가게 되고 circle의 center에도 똑같은 좌표가 나올 것이다.
그니깐 배열의 첫번째 요소를 순환할 때의 데이터만 들어가지게 되는 것!
onClick={() => handleClickMarker(data)}
handleClickMarker의 인수로 data가 들어가고
const handleClickMarker = marker => {
setSelectedMarkerId(marker.id);
setOpenCircle(!openCircle);
};
첫 번째 데이터의 id 값 즉, 1을 selectedMarkerId의 값을 업데이트 시킨다.
selectedMarkerId 값과 클릭한 marker의 id 값은 무조건 똑같을 수 밖에
만약 같다면 해당 데이터가 들어가져있는 circle을 나타내는 것!!!!
setOpenCircle
은 그냥 모달창 열었다 닫았다 하는 것
진즉 Marker와 Circle을 컴포넌트로 나누어서 따로 작성했다면 어렵게 느껴지지는 않았을 것이다. 코드가 길어지다 보니 스스로 작성한 코드에서 길을 잃게 된다.
미래의 나를 위해서라도 미리미리 컴포넌트 화 하기!
//Map.js
<StoreMarker storeMarker={storeMarker} navermaps={navermaps} />
//StoreMarker.js
import React, { useState } from 'react';
import { Marker, Circle } from 'react-naver-maps';
import getDistance from 'geolib/es/getDistance';
import DeliveryMarker from './DeliveryMarker';
const StoreMarker = ({ storeMarker, navermaps }) => {
const [selectedMarkerId, setSelectedMarkerId] = useState(0);
const [deliveryData, setDeliveryData] = useState([]);
const handleClickMarker = marker => {
setSelectedMarkerId(marker.id);
};
return (
<div>
{storeMarker.map(data => (
<div key={data.id}>
<Marker
position={
new navermaps.LatLng(data.x_coordinate, data.y_coordinate)
}
icon={{
content: `<div class="markerBoxStore">
<div class="markerCountTextStore">아이콘</div>
<p class="markerTextStore">${data.name}</p>
</div>`,
}}
title={data.name}
onClick={() => handleClickMarker(data)}
/>
{selectedMarkerId === data.id && (
<Circle
center={[data.y_coordinate, data.x_coordinate]}
radius={1000}
fillOpacity={0.5}
fillColor="#8CD790"
strokeWeight={2}
strokeColor="#5CAB7D"
strokeStyle="dashed"
clickable={true}
onClick={() => setSelectedMarkerId(0)}
/>
)}
</div>
))}
</div>
);
};