Создать массив ссылок (превышена максимальная глубина обновления) - PullRequest
0 голосов
/ 28 апреля 2020

Я использую response-native-maps и отображаю несколько маркеров с помощью array.map (). У меня также есть карусель, которая отображает некоторые фотографии и информацию о каждом маркере.

Обычно, когда пользователь нажимает на элемент в карусели, карта приближается к этому маркеру и отображает выноску, вызывая следующую функцию.

markers[index].showCallout()

, который будет отображать вызов для этого маркера. Поэтому мне нужно заполнить массив ссылками, чтобы я мог передать индекс, который покажет сноску, когда пользователь перемещает карусель.

Для начала я создал массив, который будет содержать некоторое состояние.

const [markers, setMarkers] = useState([]);

Вот функция array.map, которая генерирует все маркеры на карте.

{searchResults.map((marker, index) => {
          return (
            <MapView.Marker
              key={marker.key}
              ref={(m) => {
                setMarkers((markers) => [[...markers], m]);
              }}
              onPress={() => onMarkerPress(marker, index)}
              coordinate={{
                latitude: marker.geopoint.latitude,
                longitude: marker.geopoint.longitude,
              }}>
              <Callout>
                <Text>{marker.price}</Text>
              </Callout>
            </MapView.Marker>
          );
        })}

Я получаю ошибку «Ошибка: превышена максимальная глубина обновления. может случиться, когда компонент повторно вызывает setState внутри componentWillUpdate или componentDidUpdate. React ограничивает количество вложенных обновлений для предотвращения бесконечных циклов. "

, потому что я пытаюсь заполнить массив с помощью этой строки.

ref={(m) => {setMarkers((markers) => [[...markers], m])}}

Не уверен, есть ли другой способ сделать это.

Приведенный ниже прием работает нормально, если вы используете компоненты класса

ref={ref => this.state.markers[index] = ref}

, но я использую функциональные компоненты в своем приложении.

Вот весь код

const HomeScreen = ({navigation}) => {
  {
    /************ Array for Rendering Items in Carousel */
  }

  const searchResults = [
    {
      key: '1',
      photographerURL:
        'https://images.pexels.com/photos/598917/pexels-photo-598917.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=650&w=940',
      price: 100,
      photographerName: 'Brittany',
      geopoint: {latitude: 38.8929372, longitude: -77.0025119},
    },
    {
      key: '2',
      photographerURL:
        'https://images.pexels.com/photos/1264210/pexels-photo-1264210.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500',
      price: 200,
      photographerName: 'Franklin',
      geopoint: {latitude: 38.8963932, longitude: -77.0030197},
    },
    {
      key: '3',
      photographerURL:
        'https://images.pexels.com/photos/243757/pexels-photo-243757.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500',
      price: 50,
      photographerName: 'Bryan',
      geopoint: {latitude: 38.8925739, longitude: -76.9987113},
    },
  ];


  /**
   * Function to animate map.
   * When the user moves the carousel, the map will zoom in to
   * the region where that photographer is
   */

  const mapRef = useRef(null);
  const [carouselRef, setCarouselRef] = useState([]);
  const [markers, setMarkers] = useState([]);

  console.log(markers);

  /**
   * Zooms in on the region whenever the carousel item is changed
   */
  const onCarouselItemChange = (index) => {
    let location = searchResults[index];
    {
      mapRef.current.animateToRegion({
        latitude: location.geopoint.latitude,
        longitude: location.geopoint.longitude,
        //Zoom Level
        latitudeDelta: 0.01,
        longitudeDelta: 0.01,
      });
    }
    //markers[index].showCallout();
  };

  /**
   * When a user clicks on the marker, the carousel jumps
   * to that particular item
   */
  const onMarkerPress = (location, index) => {
    mapRef.current.animateToRegion({
      latitude: location.geopoint.latitude,
      longitude: location.geopoint.longitude,
      //Zoom Level
      latitudeDelta: 0.01,
      longitudeDelta: 0.01,
    });
    carouselRef.snapToItem(index);
  };

  return (
    <View style={styles.container}>
      {/**************** Google Maps *************** */}
      <MapView
        style={styles.map}
        ref={mapRef}
        provider={PROVIDER_GOOGLE}
        showsUserLocation
        followsUserLocation
        initialRegion={{
          latitude: 38.8929372,
          longitude: -77.0025119,
          //Zoom Level
          latitudeDelta: 0.01,
          longitudeDelta: 0.03,
        }}>
        {searchResults.map((marker, index) => {
          return (
            <MapView.Marker
              key={marker.key}
              //ref={(m) => [setMarkers((markers) => [...markers, m])]}
              onPress={() => onMarkerPress(marker, index)}
              coordinate={{
                latitude: marker.geopoint.latitude,
                longitude: marker.geopoint.longitude,
              }}>
              <Callout>
                <Text>{marker.price}</Text>
              </Callout>
            </MapView.Marker>
          );
        })}
      </MapView>
      {/***************** Carousel ***********/}
      <Carousel
        ref={(c) => {
          setCarouselRef(c);
        }}
        data={searchResults}
        horizontal
        containerCustomStyle={styles.carousel}
        onSnapToItem={(index) => onCarouselItemChange(index)}
        layout={'default'}
        //layoutCardOffset={`50`}
        sliderWidth={screenWidth}
        itemWidth={screenWidth * 0.8}
        itemHeight={400}
        pagingEnabled={true}
        showsHorizontalScrollIndicator={false}
        renderItem={({item}) => (
          <Item
            photographerName={item.photographerName}
            uri={item.photographerURL}
            price={item.price}
          />
        )}
        keyExtractor={(item) => item.key}
      />
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    ...StyleSheet.absoluteFill,
  },
  map: {
    ...StyleSheet.absoluteFill,
  },
  carousel: {
    position: 'absolute',
    bottom: 0,
    marginBottom: '5%',
  },
});

export default HomeScreen;
...