Closed joonas-yoon closed 1 year ago
Button을 추가해서 Map 컴포넌트를 다시 그리도록 해도 표시가 되지 않네요 😢
아래와 같이 onCreate
콜백을 등록하면 콘솔에 찍히기는 하는 걸 보면, 객체는 생성되었으나 렌더링되는 부분에서 업데이트가 되지 않는 것 같습니다.
{data.map(({ key, lat, lng }) => (
<CustomOverlayMap
key={key}
onCreate={console.log}
...
안녕하세요, 해당 라이브러리는 동적으로 다양한 Overlay를 랜더링 하는 것에 대해서 지원하고 있습니다!
일단 첨부 하신 코드에서 일부 문제점이 발견되어서 해당 부분을 수정 후에 사용하시면 될 것 같습니다.!
ps. 현재 현역 군인 신분이여서 답변이 많이 제한될 수 있습니다. (훈련 및 당직 근무) 전역하고 싶네요…
// App.tsx
…
function MapLoader(
props: KakaoMapSDK.MapProps | React.CSSProperties
) {
const [container, setContainer] = useState<React.ReactElement>()
useEffect(() => {
const script: Loader = new Loader({
appkey: 'KAKAO_MAP_SDK_WEB_API_KEY',
libraries: ["services", "clusterer"],
retries: 3,
})
script.load().then(() => {
setContainer(<Map {...(props as KakaoMapSDK.MapProps)} />) // 로드가 완료되었을 때 해당 시점에서의 props를 인자로 주어 Map Element를 생성하여 저장하는 것을 볼 수 있습니다..
})
}, [setContainer]) // 하지만 해당 Effect의 발생조건은 최초 렌더링 혹은 setContainer가 변경되었을 때 동작되도록 작성이 되어 있습니다.
// 즉 props의 children 객체가 변경되어도 해당 effect는 다시 발생하지 않고 container 객체가 업데이트가 되는 일이 없기 때문에 리렌더링이 발생하지 않은 것 입니다.
return <>{container}</>
}
…
가장 좋은 수정 방법으로는 html에 script 태그를 직접 추가 하거나, useInjectKakaoMapApi
hook를 사용해주세요. (만약 버그가 있다면 리포트 부탁드립니다.)
답변 감사합니다. static 하게 html에 직접 script 태그를 추가하기에는 API KEY 를 동적으로 로딩하는 구조를 유지하고 싶어서 어렵습니다 😢
useInjectKakaoMapApi
훅은 한번 살펴볼게요 :)
말씀해주신 부분에서, setContainer로 state를 변경하면 return <>{container}</>
부분이 리렌더링되어서 반영되지 않나요?
그리고 말씀해주신대로라면, effect의 deps에 적당한 props를 추가하면 될 수 있겠는데 매 번 맵을 새로 렌더링하면서 깜박거리지 않을까요?
군복무는 ㅎㅎ 응원하겠습니다.
useEffect
에 deps
array에 적당한 값을 넣어서 동작시킬 수도 있지만 그렇게 되면 Loader
객체를 필요 없이 중복되어 계속 생성하는 문제가 발생합니다.
Map
를 리렌더링 한다고 하였을 때 내부에서 kakao.Map 객체를 유지하고 추가적으로 변한 Props만 반영하도록 처리되어 있어서, 완벽하게 Rendering Tree에서 제거되지 않는 이상 깜빡임에 대해서는 걱정 하지 않으셔도 됩니다.
useInjectKakaoMapAPI
를 사용하지 않고 Loader
를 이용하여 사용하신다면 아래와 같이 작성하여 사용하셔도 됩니다.!
// App.tsx
import React, { useEffect, useState, useMemo } from "react"
import KakaoMapSDK, { Map, Loader } from "react-kakao-maps-sdk"
import { CustomOverlayMap } from "react-kakao-maps-sdk"
function MapLoader(
props: KakaoMapSDK.MapProps | React.CSSProperties
) {
useEffect(() => {
const script: Loader = new Loader({
appkey: 'KAKAO_MAP_SDK_WEB_API_KEY',
libraries: ["services", "clusterer"],
retries: 3,
})
script.load()
}, [])
return <Map {...props} />
}
const Circle = () => (
<div style={{
width: '64px',
height: '64px',
borderRadius: '50%',
background: 'dodgerblue',
}} />
)
export function App(props) {
const [overlays, setOverlays] = useState([])
useEffect(() => {
setOverlays([
{ key: "marker-1", lat: 37.52897, lng: 126.917101 },
{ key: "marker-2", lat: 37.5268796, lng: 126.919094 },
{ key: "marker-3", lat: 37.527502, lng: 126.920146 },
])
}, [])
return (
<MapLoader
center={{
lat: 37.52897,
lng: 126.917101,
}}
level={3}
style={{
width: '1000px',
height: '540px',
}}>
{overlays.map(({ key, lat, lng }) => (
<CustomOverlayMap
key={key}
position={{
lat,
lng,
}}
>
<Circle />
</CustomOverlayMap>
))}
</MapLoader>
);
}
// Log to console
console.log('Hello console')
아하.. 내부적으로 Context 관리를 해주고 있었군요?
script load 에 콜백을 사용해야 할 줄 알았는데, 감사합니다 ㅎㅎ
코드 반영해서 확인해보고 다시 말씀드리겠습니다 :>
문제는 해결되었습니다 감사합니다 ^^
그런데 Loader를 사용하는 것도 playground 에서는 모듈화해도 잘 되는데, 프로젝트에 적용하려니까 다른 부분에서 꼬인 것 같아서 useInjectKakaoMapAPI
를 사용하는 것으로 바꿨습니다 :)
이슈는 닫도록 하겠습니다 😃
안녕하세요,
CustomOverlayMap 클래스를 state로 관리했을 때, 동적으로 표시할 수 있는 방법이 있나요?
위 코드는 정상적으로 표시되지만, 다음과 같이 useEffect 로 overlay를 나중에 추가하게 되면 렌더링이 안되고 있어서요.
이 경우에는 Map을 다시 렌더링해야하나요?
코드를 어떻게 수정하면 좋을 지 모르겠습니다.
Code snippet 아래 링크로 전체 코드를 실행해보실 수 있는데 참고해주세요. https://playcode.io/1277159