zeakd / react-naver-maps

React Navermaps API integration for modern development.
https://zeakd.github.io/react-naver-maps/
118 stars 23 forks source link

React와 js 연동 #15

Closed bearics closed 5 years ago

bearics commented 5 years ago

개발자님, react-naver-maps 배포해주시면서 react를 쉽게 사용하고 있는데, Javascript하고도 같이 연동하고 싶어 몇가지 테스트를 해봤는데, 이에 대한 몇 가지 팁을 얻을 수 있을까요?

질문1

개발자님이 만들어주신 ref를 좀 손쉽게 사용을 하고 싶은데, 어떻게 연결을 해야 할까요?

참고 예제 사이트 위 예제 사이트를 보면 naverRef={ref => { this.mapRef = ref }} 를 받아서 this.naverMapRef.getBounds()으로 사용 하는 거 같은데, 제대로 동작을 하지 않고 아래 에러코드를 내뿜습니다. 어떻게 사용을 하면 되는건가요?

소스코드

import {  RenderAfterNavermapsLoaded,  NaverMap, Circle } from "react-naver-maps";

const cx = classNames.bind(styles);

class Map extends Component {

  render() {
    return (
      <div className={cx("map-panel")}>
        <Header>위치</Header>
        <div className={cx("body")}>
          <RenderAfterNavermapsLoaded ncpClientId="#####">
          <NaverMap 
            naverRef={ref => { this.mapRef = ref }}
            id='maps-examples-map-simple'
            style={{
              width: '100%',
              height: '600px',
            }}
            defaultCenter={{x: 126.5343612, y: 33.3590625}}
          >
          </NaverMap>
          </RenderAfterNavermapsLoaded>
        </div>
        <Footer />
      </div>
    );
  }

  componentDidMount() {
    // map이 생성될 때의 bounds를 알기 위해 method를 이용합니다.
    console.log(this.mapRef.getBounds());

  }

}

export default Map;

에러코드 Cannot read property 'getBounds' of undefined

질문2

질문1에 대한 추가적인 질문입니다. react에서 외부 라이브러리를 사용 할때 .js를 제공해주기 때문에 import 받아서 사용을 했는데, naver-map 불가능 한 것 같습니다. 그래서 <script></script>를 사용하려 했지만, 개발자님이 이러한 수고를 덜어 주기 위해 <RenderAfterNavermapsLoaded/>를 만든 것 같아서 사용해보려고 합니다. 아래와 같은 코드로 사용을 할 수 있는지 궁금합니다. this.mapRef를 통해 return에 있는 <NaverMap/>를 가져와 javascript와 같이 사용 할 수 있을까요?

소스코드

import {  RenderAfterNavermapsLoaded,  NaverMap, Circle } from "react-naver-maps";

const cx = classNames.bind(styles);

class Map extends Component {

  render() {
    return (
      <div className={cx("map-panel")}>
        <Header>위치</Header>
        <div className={cx("body")}>
          <RenderAfterNavermapsLoaded ncpClientId="####">
          <NaverMap 
            naverRef={ref => { this.mapRef = ref }}
            id='maps-examples-map-simple'
            style={{
              width: '100%',
              height: '600px',
            }}
            defaultCenter={{x: 126.5343612, y: 33.3590625}}
          >
          </NaverMap>
          </RenderAfterNavermapsLoaded>
        </div>
        <Footer />
      </div>
    );
  }

  componentDidMount() {
    var marker = new naver.maps.Marker({
        position: new naver.maps.LatLng(37.3595704, 127.105399),
        map: this.mapRef
    });
  }
}

export default Map;
zeakd commented 5 years ago

@bearics 님 이슈 감사합니다. 😊

  1. \ 의 경우 비동기로 navermaps js 파일을 요청하여 children대신 null을 render하였다가, load되면 children을 그려주는 Util Component 입니다. 위 경우를 예로 들면

Map render -> RenderAfterNavermapsLoaded render -> children null -> navermaps js 파일 요청 -> Map componentDIdMount -> navermaps .js loaded -> NaverMap render

의 순서로 진행됩니다. Map 의 componentDidMount가 먼저 발생하고 load 된 후에야 비로소 NaverMap이 mount되기 때문에 componentDidMount시에는 ref가 아직 없게되는 것입니다.

따라서 안에서 componentDidMount로 naverRef를 컨트롤하기 위해서는 \ 전체가 \ 로 감싸져 있어야 합니다.

<RenderAfterNavermapsLoaded>
    <Map />
</RenderAfterNavermapsLoaded>

이 부분은 잘못 사용시 경고가 필요하겠네요. 헷갈릴 여지가 있는 것 같습니다.

  1. React에서 ref로 접근하는 경우, 이는 React Element를 가리키게 되어있습니다. react-naver-maps 또한 naverRef 로 접근하는 경우 NaverMap의 클래스 인스턴스를 가리키게 됩니다. 이 클래스 인스턴스에 getBounds라는 메소드가 생성되어 있기 떄문에 mapRef.getBounds() 처럼 사용할 수 있게됩니다. 하지만 말씀하신대로 navermaps의 Marker등을 직접 사용하기위해 naver.maps.Map의 map인스턴스를 직접참고하려면 mapRef.instance 를 사용하시면 됩니다. 문서에 적어두었으니 참고해주세요.

컴포넌트 인스턴스에 접근하기

아, 물론 이슈 1. 을 해결하셔야 이슈 2. 도 적용되니 1. 을 먼저 해결해주세요.

bearics commented 5 years ago

감사합니다. 덕분에 이슈 1, 2 모두 해결 할 수 있었습니다.

App.js

import React, { Component } from "react";
import logo from "./logo.svg";
import "./App.css";
import { RenderAfterNavermapsLoaded, NaverMap } from "react-naver-maps";
import Map from "./Map";

class App extends Component {
  render() {
    return (
      <div className="App">
        <div>
          <RenderAfterNavermapsLoaded
            ncpClientId="####"
            error={<p>Maps Load Error</p>}
            loading={<p>Maps Loading...</p>}
          >
            <Map/>
          </RenderAfterNavermapsLoaded>
        </div>
      </div>
    );
  }

}

export default App;

Map.js

import React, { Component } from "react";
import { NaverMap } from "react-naver-maps";

class Map extends Component {
  render() {
    return (
      <div>
          <NaverMap
            mapDivId={"maps-getting-started-uncontrolled"} // default: react-naver-map
            style={{
              width: "100%",
              height: "800px"
            }}
            naverRef={ref => { this.mapRef = ref }}
            defaultCenter={{ lat: 37.3595704, lng: 127.105399 }}
            defaultZoom={10}
          />
      </div>
    );
  }

  componentDidMount() {
    console.log(this.mapRef.getBounds());
    var marker = new window.naver.maps.Marker({
      position: new window.naver.maps.LatLng(37.3595704, 127.105399),
      map: this.mapRef.instance
  });
  }
}

export default Map;
Screen Shot 2019-04-09 at 3 34 50 PM

친절한 답변 감사합니다. 😊