2017-09-05 2 views
1

다양한 탭이있는 탐색 모음이있는 SPA 응용 프로그램을 빌드하고 있습니다. 탭을 선택하면 redux를 통해 작업을 전달하고 어떤 탭이 선택되었는지에 따라 AppBody 구성 요소가 다시 나타납니다 (renderAppBody() : AppBody 참조).React Tab 구성 요소에서 OpenLayers 맵 관리

내 문제는 탭 중 하나에 OpenLayers 맵이 있어야한다는 것입니다. DOM에 이미 존재하는 요소를 대상으로해야하므로지도를 처음으로 탑재하는 데 많은 어려움을 겪었습니다. 나는 componentDidMount를 재정 의하여 이런 짓을 :

MapBody.js

import React from 'react'; 
import "ol/ol.css" 
import Map from 'ol/map' 
import View from 'ol/view' 
import Tile from 'ol/layer/tile' 
import OSM from 'ol/source/osm' 

import "../../sass/App.scss"; 


var map = new Map({ 
    layers: [ 
    new Tile({ 
     source: new OSM() 
    }), 
    ], 
    view: new View({ 
    center: [0, 0], 
    zoom: 4 
    }) 
}); 


const MapBody = React.createClass({ 
    render: function() { 
    return (<div id="map"></div>); 
    }, 
    componentDidMount: function() { 
    map.setTarget("map"); 
    } 
}); 

export default MapBody; 

이 내가 탭을 전환 할 때마다, 내지도 요소가/파괴 제거하고 다음 탭의 내용으로 대체되는 것을 의미한다. 그 효과는 처음으로 렌더링 할지도 탭을 선택하지만 다른 탭을 선택한 다음지도 탭을 다시 선택하면지도가 렌더링되지 않습니다.

내 접근 방식은 내가 원하는 결과에 본질적으로 결함이 있습니까? 이것은 나의 첫 번째 largish React 프로젝트이기 때문에이 동작을 설계하는 최선의 방법이 확실하지 않습니다.

내가해야 :

  • 지도 항목에 대한 참조를 유지하고 다시 쓰게 그것을 reappend? (문제가있는 것 같습니다)
  • 탭을 바꾸지 않고 숨기시겠습니까? (또한 문제가있는 것 같습니다)
  • MapBody에는 두 가지 상태, 즉 visibleinactive이 있습니다. 그런 다음 항상 화면에 렌더링하고 상태에 따라 CSS로 숨 깁니다 (해킹 것 같음)
  • 좀 더 세련 되나요?

AppBody.js

import React from 'react'; 
import { connect } from 'react-redux'; 
import Activity from '../components/body/Activity' 
import CategoryBody from '../components/body/CategoryBody' 
import MapBody from '../components/body/MapBody' 
import Search from '../components/body/Search' 

import tabs from "../actions/tabDefinitions.js" 

import "../sass/App.scss"; 

function renderAppBody(activeTab) { 
    switch (activeTab) { 
    case tabs.T_CATEGORIES: 
     return <CategoryBody /> 
    case tabs.T_MAP: 
     return (<MapBody />) 
    case tabs.T_SEARCH: 
     return <Search /> 
    case tabs.T_ACTIVITY: 
     return <Activity /> 
    default: 
     return <div>Oops! Something went wrong :(</div> 
    } 
} 

const AppBody = ({activeTab}) => (
    <div className="frame_wrapper"> 
     {renderAppBody(activeTab)} 
    </div> 
) 


const mapStateToProps = (state) => ({ 
    activeTab: state.activeTab, 
}); 

export default connect(mapStateToProps)(AppBody); 

감사합니다!

답변

0

선택한 탭과 관계없이 항상 MapBody 구성 요소를 AppBody에 추가하는 결과가 발생했습니다. 그런 다음 active 소품을 MapBody에 추가하여 CSS 클래스를 표시/숨기기를 추가했습니다. 그렇게하면 탭이 변경 될 때 맵 컨테이너가 제거되거나 재설정되지 않으므로 상태가 잘 유지됩니다. 내 접근 방식은 특별히 우아하지 않습니다 (읽기 : 더럽고 더러운 해킹입니다). 그럼에도 불구하고 작동합니다.

MapBody 렌더링 기능이되었다 :

render: function() { 
    return (<div id="map" 
       className={this.props.active ? "active_map" : "inactive_map"}> 
      </div>); 
} 

대부분가 원하는 동작 준 다음 CSS 추가하여 :

.inactive_map { 
    display: none; 
} 

을이 전환 할 때지도 컨테이너가 제대로/숨겨진 렌더링되는 원인 지도 캔버스는 회색이었고 어떤 내용도 렌더링하지 않았습니다. 이 문제를 해결하기 위해 componentDidUpdate()을 무시하고 map.updateSize()을 호출하여지도 뷰포트 크기를 다시 계산해야합니다.최종 코드 :

MapBody.js

const MapBody = React.createClass({ 
    render: function() { 
    return (<div id="map" 
       className={this.props.active ? "active_map" : "inactive_map"}> 
      </div>); 
    }, 
    componentDidMount: function() { 
    this.props.map.setTarget("map"); 
    }, 
    componentDidUpdate: function() { 
    this.props.map.updateSize(); 
    } 
}); 

AppBody.js

function renderAppBody(activeTab) { 
    switch (activeTab) { 
    case tabs.T_CATEGORIES: 
     return <CategoryBody /> 
    case tabs.T_MAP: 
     return ""; 
    case tabs.T_SEARCH: 
     return <Search /> 
    case tabs.T_ACTIVITY: 
     return <Activity /> 
    default: 
     return (<div>Oops! Something went wrong :(</div>) 
    } 
} 

const AppBody = ({activeTab}) => (
    <div className="frame_wrapper"> 
     {renderAppBody(activeTab)} 
     <Map active={activeTab == tabs.T_MAP}/> 
    </div> 
) 
관련 문제