在一个阵营的选项卡组件

问题描述:

管理一个地图的OpenLayers我的建筑内设有各种选项卡的导航栏SPA应用。当选中选项卡时,我会通过REDX发送一个动作,并且AppBody组件会根据选择哪个选项卡来重新显示自己(请参阅中的renderAppBody())。在一个阵营的选项卡组件

我的问题是,标签必须包含的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; 

这意味着,每当我切换标签,我的地图元素被破坏/脱除,用下一个标签的内容取代。其效果是,我第一次选择渲染的地图选项卡,但如果我选择另一个选项卡,然后重新选择地图选项卡,地图将不会渲染。

是我的方法固有的缺陷的,我想要的结果?这是我第一个较大的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); 

谢谢!

我最终总是加上MapBody组分AppBody无论所选标签的。然后,我添加了active prop到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> 
)