참고자료
import React, { useRef } from 'react';
const MapRender = ({ show, setShow }) => {
// 1. useRef()를 사용하여 ref객체를 만듦
const mapContainer = useRef();
// 지도를 생성한다
useEffect(() => {
// 3. ref.current는 이제 div를 가르키게됨.
let map = new kakao.maps.Map(mapContainer.current, mapOption);
}
return ( // 2. 선택하고 싶은 dom요소에 ref값을 설정해줌.
<div id="map" className="map" ref={mapContainer} style={style}>
)
};
지도를 렌더한 후, toggle버튼을 누르면 지도의 사이즈가 커진 후 다시 map인스턴스 객체에 있는 relayout함수를 호출해야 했다.
그러나 지도의 사이즈를 변경하는 코드는 MapRender컴포넌트의 스코프에서 실행되는데, 지도를 relayout하는 메서드는 map 인스턴스 객체에 있기 때문에 스코프가 달라서 map객체에 접근이 불가능 했다.
따라서 new map을 MapRender컴포넌트의 변수에 두어 접근하기로 했다.
그러나 tooggle버튼을 누르면 state가 변경되어 지도 사이즈가 변경되어 MapRender컴포넌트가 리렌더링 되는데,
컴포넌트가 리렌더링 될 때마다 변수가 새로 초기화되서 이전값이 유지되지 않음.
const MapRender = ({ show, setShow }) => {
const [style, setStyle] = useState({
width: '100%',
height: 'calc(100vh - 100px)',
});
// onClickToggle함수 코드 생략... (style의 값이 바뀐다.)
let map = null;
console.log(map); // ✔️ 2. 리렌더링 되면 계속 null로 나오게 됨.
useEffect(() => { // 1. 지도를 생성한다
map = new kakao.maps.Map(mapContainer.current, mapOption);
},[])
useEffect(() => {
map.relayout();
// 3. style이 바뀔 때마다 MapRender 컴포넌트는 리렌더링 되는데
// 그때마다 let map은 null로 초기화 된다.
// 따라서 map 인스턴스 객체가 유지되지 않음
}, [style]);
return (
<div id="map" className="map" ref={mapContainer} style={style}>
<button onClick={onClickToggle}> 토글버튼 </button>
</div>
)
}
useRef를 통해 컴포넌트가 리렌더링되도 new map은 변하지 않는 값으로 만들어 사용하기로 했다.
const MapRender = ({ show, setShow }) => {
const [style, setStyle] = useState({
width: '100%',
height: 'calc(100vh - 100px)',
});
// onClickToggle함수 코드 생략... (style의 값이 바뀐다.)
const map = useRef(); // 1. useRef를 사용
useEffect(() => { // 지도를 생성한다
// 2. map.current에 kakao Map인스턴스 객체를 넣음
map.current = new kakao.maps.Map(mapContainer.current, mapOption);
},[])
useEffect(() => {
map.current.relayout();
// 3. Map컴포넌트의 스코프에 kakao Map인스턴스 객체가 있기 때문에
// map 인스턴스 객체에 접근하여, relayout메서드를 실행할 수 있다.
}, [style]);
return (
<div id="map" className="map" ref={mapContainer} style={style}>
<button onClick={onClickToggle}> 토글버튼 </button>
</div>
)
}
컴포넌트의 state가 업데이트되서 재실행되면, 별도의 스코프가 생성되서 변수가 계속 초기화됨.
그러나 useRef를 사용하면, 별도의 공간이 만들어져서 여러 스코프에서 한 useRef를 참조할 수 있다.
따라서 new map 인스턴스를 변수에 담는게 아니라, useRef.current에 담는것임!