使用react-native-maps动态呈现多个自定义标记

时间:2018-06-08 12:40:11

标签: javascript reactjs react-native react-native-maps

我在地图上基于活动过滤器渲染标记时遇到了一个主要的性能问题。

我有一个数据结构,类似于

const businesses = [
  {
    ...location,
    businessType: 'Market'
  },
  ...etc
]

目前该数据集中有150个项目。默认情况下会渲染所有标记。目前我正在随机生成标记数据。

现在,我也有可以切换的类别,如果类别被切换=>渲染该业务类型。

现在,每当我切换类别时,我的JS线程跳转到0 fps并且UI线程被阻止。

这是我目前的代码:

import React, { PureComponent } from 'react';
import { InteractionManager } from 'react-native';
import generateRandomMapData from 'utils/generateRandomMapData';
import CustomMarker from './CustomMarker';

const CENTER_OF_BERLIN = {
  latitude: 52.5200,
  longitude: 13.4050,
};

const RADIUS = 5000;
const AMOUNT_OF_MARKERS = 150;

class Markers extends PureComponent {
  constructor(props) {
    super(props);

    this.state = {
      markers: null
    }
  }
  componentDidMount() {
    this.interactionHandle = InteractionManager.runAfterInteractions(() => {
      this.setState({ markers: generateRandomMapData(CENTER_OF_BERLIN, RADIUS, AMOUNT_OF_MARKERS) }, () => {
        this.interactionHandle = null;
      })
    })
  }
  componentWillUnmount() {
    if (this.interactionHandle) this.interactionHandle.cancel();
  }
  renderMarkers() {
    const { markers } = this.state;

    if (markers && markers.length) {
      return markers.map((b, i) => <CustomMarker location={b.location} key={i} businessType={b.businessType} />)
    }

    return null;
  }
  render() {
    return this.renderMarkers()
  }
}

export default Markers;

个人标记文件

import React, { PureComponent } from 'react';
import { View, InteractionManager } from 'react-native'
import { Marker } from 'react-native-maps';
import { connect } from 'react-redux';
import SVG from 'components/svg/SVG'

const BUSINESS_COLORS = {
  market: '#EC6D52',
  farm: '#763DAB',
  restaurant: '#C45D72',
  UrbanFarm: '#4B85DD',
  store: '#65A077',
}

class CustomMarker extends PureComponent {
  constructor(props) {
    super(props);

    this.state = {
      shouldRender: false
    }
  }
  componentWillMount() {
    const { businessType, categories } = this.props;

    this.interactionHandle = InteractionManager.runAfterInteractions(() => {
      if (this._getActiveCategories(categories).includes(businessType) !== this.state.shouldRender) {
        this.setState({ shouldRender: this._getActiveCategories(categories).includes(businessType) }, () => {
          this.interactionHandle = null;
        });
      }
    });
  }
  componentDidUpdate() {
    if (this.interactionHandle) this.interactionHandle.cancel();

    const { businessType, categories } = this.props;
    const { shouldRender } = this.state;

    this.interactionHandle = InteractionManager.runAfterInteractions(() => {
      if (this._getActiveCategories(categories).includes(businessType) !== shouldRender) {
        this.setState({ shouldRender: this._getActiveCategories(categories).includes(businessType) }, () => {
          this.interactionHandle = null;
        })
      }
    });
  }
  componentWillUnmount() {
    if (this.interactionHandle) this.interactionHandle.cancel();
  }
  _getActiveCategories(categories) {
    const active = [];

    for (let category of categories) {
      if (category.active) {
        active.push(category.icon)
      }
    }

    return active;
  }
  render() {
    const { businessType, location } = this.props;
    const { shouldRender } = this.state;
    const iconColor = BUSINESS_COLORS[businessType.toLowerCase()];

    const opacity = shouldRender ? 1.0 : 0.0;

    return (
      <Marker coordinate={{ ...location }} opacity={opacity}>
        <View style={{ width: 29, height: 36 }}>
          <SVG icon="Marker" width="29" height="36" fill={iconColor} />
        </View>
      </Marker>
    );
  }
}

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

export default connect(mapStateToProps, {
})(CustomMarker);

类别本身存在于Redux中,并且标记基于此进行映射。

即使使用了setState,似乎同时在25个受影响的标记上调用InteractionManager也非常繁重。

如何优化此性能?

0 个答案:

没有答案