[기업협업]Day10. map 돌린 객체에 onClick 따로 적용하기

Joah·2022년 8월 10일
0

기업협업

목록 보기
10/15
post-thumbnail

map 돌리고 onClick 따로 적용하기

네이버 지도에 동 marker를 map함수로 나타냈다.

각각의 marker를 클릭하면 해당 marker에 해당하는 circle이 나타난다.

하지만 marker 자체를 map을 돌렸기 때문에 1번 marker를 클릭하면 1,2,3 marker 각각에 대한 circle을 모두 그린다.

나는 1번 marker에 해당하는 circle만 띄우고 싶다.

문제의 모든 서클 나타내기


⛳ Marker의 id 값을 활용하자

  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.idtrue


⛳ 해결

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은 그냥 모달창 열었다 닫았다 하는 것


⛳ Long Story Short

진즉 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>
  );
};
profile
Front-end Developer

0개의 댓글