Reactjs React Native:如何在每次状态更新时阻止贴图标记重新渲染

Reactjs React Native:如何在每次状态更新时阻止贴图标记重新渲染,reactjs,react-native,react-native-ios,react-native-maps,Reactjs,React Native,React Native Ios,React Native Maps,我有一个组件,它有一个带有多个自定义标记的地图,用于不同的位置,还有一个带有相同位置的卡片的旋转木马。当用户按下标记时,应显示详图索引,并在标记旁边(但在详图索引之外)显示位置名称 但是,由于我在onRegionChangeComplete中更新了状态,如果用户移动地图,然后快速按下标记(在状态从onRegionChangeComplete中调用setState完成更新之前),那么标记将在触发onPress事件之前重新呈现,而且事件永远不会被触发 一种解决方案可能是使用shouldCompone

我有一个组件,它有一个带有多个自定义标记的地图,用于不同的位置,还有一个带有相同位置的卡片的旋转木马。当用户按下标记时,应显示详图索引,并在标记旁边(但在详图索引之外)显示位置名称

但是,由于我在
onRegionChangeComplete
中更新了状态,如果用户移动地图,然后快速按下标记(在状态从
onRegionChangeComplete
中调用
setState
完成更新之前),那么标记将在触发
onPress
事件之前重新呈现,而且事件永远不会被触发

一种解决方案可能是使用
shouldComponentUpdate
,但是,文档中指出,它只应用于性能优化,而不应防止重新渲染(),但更重要的是,my
componentdiddupdate
函数具有一些条件逻辑,这取决于
shouldComponentUpdate
中设置的区域,以及其他条件操作,所以我不想阻止重新呈现整个组件,只是不必要地重新呈现标记

我还使用了中提到的性能优化,将makers包装在一个实现
shouldComponentUpdate
getDerivedStateFromProps
的组件中,我不完全确定这是否有用,因为父组件似乎只是在重新创建我所有的优化标记,而不是使用它们的优化来处理重新渲染。此外,即使我不使用包装标记,而是使用传统的自定义标记,我仍然存在相同的问题

我也在react native maps上对此提出了一个问题,但尚未得到回应:

我的“onRegionComplete”函数,用于在移动地图时更新状态。为了简洁起见,我删除了一些其他条件状态更新:

onRegionChangeComplete = (region) => {
    const nextState = { };
    nextState.region = region;

    if (this.state.showNoResultsCard) {
      nextState.showNoResultsCard = false;
    }

    .
    .
    .

    this.setState({ ...nextState });

    this.props.setSearchRect({
      latitude1: region.latitude + (region.latitudeDelta / 2),
      longitude1: region.longitude + (region.longitudeDelta / 2),
      latitude2: region.latitude - (region.latitudeDelta / 2),
      longitude2: region.longitude - (region.longitudeDelta / 2)
    });
  }
使用更传统的标记(而不是经过优化的版本)的地图视图:

更新状态,然后快速按下标记将导致onPress事件不触发。此外,每次更新父组件时,都会重新渲染/重新创建标记。(我之所以说“重新创建”,是因为看起来标记正在重新渲染,甚至没有触发
shouldcomponentupdate
e或
componentdiddupdate


是否有任何方法可以在不强制重新渲染标记的情况下更新
onRegionChangeComplete
中的状态?

对于碰巧遇到此问题的任何其他人,问题是我随机生成标记的键,导致父组件在每次重新渲染时创建新标记


具体来说,行
key={Shortid.generate()}
就是问题所在。

您是否设法让它工作了?让我们知道这方面的解决方法。我也面临着类似的问题。@Balasubramanian问题是我随机生成标记的键,所以父组件每次重新渲染时都会重新创建它们。我在问题(#2860)中创建并链接到的github问题中描述了这一点,希望您已经看到了这一点并解决了您的问题。
<MapView // show if loaded or show a message asking for location
    provider={PROVIDER_GOOGLE}
    style={{ flex: 1, minHeight: 200, minWidth: 200 }}
    initialRegion={constants.initialRegion}
    ref={this.mapRef}
    onRegionChange={this.onRegionChange}
    onRegionChangeComplete={this.onRegionChangeComplete}
    showsUserLocationButton={false}
    showsPointsOfInterest={false}
    showsCompass={false}
    moveOnMarkerPress={false}
    onMapReady={this.onMapReady}
    customMapStyle={mapStyle}
    zoomTapEnabled={false}
    >

        {this.state.isMapReady && this.props.places.map((place, index) => {
            const calloutText = this.getDealText(place, 'callout');
            return (
                <Marker
                    tracksViewChanges
                    key={Shortid.generate()}
                    ref={(ref) => { this.markers[index] = ref; }}
                    coordinate={{
                        latitude: place.getLatitude(),
                        longitude: place.getLongitude()
                    }}
                    onPress={() => { this.onMarkerSelect(index); }}
                    anchor={{ x: 0.05, y: 0.9 }}
                    centerOffset={{ x: 400, y: -60 }}
                    calloutOffset={{ x: 8, y: 0 }}
                    calloutAnchor={{ x: 0.075, y: 0 }}
                    image={require('../../Assets/icons8-marker-80.png')}
                    style={index === this.state.scrollIndex ? { zIndex: 2 } : null}
                >
               {this.state.scrollIndex === index &&
                    <Text style={styles.markerTitle}>{place.getName()}</Text>}

                  <Callout onPress={() => this.onCalloutTap(place)} tooltip={false}>
                    <View style={{
                      borderColor: red,
                      width: 240,
                      borderWidth: 0,
                      borderRadius: 20,
                      paddingHorizontal: 8,
                      flexDirection: 'column',
                      justifyContent: 'flex-start',
                      alignItems: 'center'
                    }}
                    >
                      <Text style={styles.Title}>Now:</Text>
                      <View style={{
                        width: 240,
                        flexDirection: 'column',
                        justifyContent: 'space-evenly',
                        alignItems: 'flex-start',
                        paddingHorizontal: 8,
                        flex: 1
                      }}
                      >
                        {calloutText.Text}
                    </View>
                </View>
            </Callout>
        </Marker>
        );
    }) 
}

</MapView>
onMarkerSelect(index) {
    this.setState({ scrollIndex: index });
    this.carousel._component.scrollToIndex({
      index,
      animated: true,
      viewOffset: 0,
      viewPosition: 0.5
    });

    this.markers[index].redrawCallout();
}