У меня есть приложение, похожее на airbnb, с карточками слева и картой Google справа (с использованием пакета response-google-maps)
Я хотел бы выделить (в приведенном ниже коде с помощью анимации) маркер, когда пользователь наводит курсор на соответствующую карточку.
Мне действительно удалось это сделать (см. Код ниже), но проблема в том, что компонент карты перерисовывается, когда пользователь наводит курсор на другую карту.
Есть ли способ сделать это без необходимости каждый раз заново рендерить карту?
Мой App.js (упрощенный для понимания):
import React from "react";
import { Meals } from "../api/meals.js";
import { Restaurants } from "../api/restaurants.js";
import MealCard from "./MealCard";
import MealsMap from "./MealsMap";
class App extends React.Component {
constructor() {
super();
this.state = {
highlightedMarker: ""
};
this.renderMeals = this.renderMeals.bind(this);
this.highlightMarker = this.highlightMarker.bind(this);
}
renderMeals() {
return this.props.meals.map(m => (
<div
className = "col-sm-6 col-xs-12 "
key = {m._id}
onMouseOver = {() => this.highlightMarker(m.restaurant)}
>
<MealCard
name = {m.name}
restaurant = {
this.props.restaurants.find(r => r._id === m.restaurant).name
}
image = {m.image}
address = {
this.props.restaurants.find(r => r._id === m.restaurant).address
}
/>
</div>
));
}
renderMap() {
return (
<MealsMap
restaurants = {this.props.restaurants}
highlightedMarker = {this.state.highlightedMarker}
/>
);
}
highlightMarker(restaurantId) {
this.setState({ highlightedMarker: restaurantId });
}
render() {
return (
<div>
<div className = "app-wrapper" style = {{ display: "flex" }}>
<div className = "container">
<div className = "row">{this.renderMeals()}</div>
</div>
{this.renderMap()}
</div>
</div>
);
}
}
и мой MealsMap.js:
import React from "react";
import { withGoogleMap, GoogleMap, Marker } from "react-google-maps";
class MealsMap extends React.Component {
render() {
const GoogleMapMeals = withGoogleMap(props => (
<GoogleMap
defaultCenter = {{ lat: 50.6320134, lng: 3.0568584 }}
defaultZoom = {13}
>
{this.props.restaurants.map(r => (
<Marker
key = {r._id}
position = {{ lat: Number(r.lat), lng: Number(r.lng) }}
animation = {
this.props.highlightedMarker === r._id
? google.maps.Animation.BOUNCE
: ""
}
/>
))}
</GoogleMap>
));
return (
<GoogleMapMeals
containerElement = {
<div
style = {{
flex: "0 0 400px",
height: "100vh",
position: "sticky",
top: "0"
}}
/>
}
mapElement = {
<div
style = {{
height: "100%",
width: "100%",
position: "absolute",
top: "0px",
left: "0px",
backgroundColor: "rgb(229, 227, 223)"
}}
/>
}
/>
);
}
}
export default MealsMap;
Вы не хотите определять компонент GoogleMapMeals
внутри метода рендеринга MealsMap
, поскольку это приведет к созданию нового компонента при каждом рендеринге, который заставит React размонтировать предыдущий и создать совершенно новый.
Вместо этого вы можете определить GoogleMapMeals
вне метода рендеринга.
Пример
const GoogleMapMeals = withGoogleMap(props => (
<GoogleMap
defaultCenter = {{ lat: 50.6320134, lng: 3.0568584 }}
defaultZoom = {13}
>
{props.markers.map(r => (
<Marker
key = {r._id}
position = {{ lat: Number(r.lat), lng: Number(r.lng) }}
animation = {
props.highlightedMarker === r._id
? google.maps.Animation.BOUNCE
: ""
}
/>
))}
</GoogleMap>
));
class MealsMap extends React.Component {
render() {
return (
<GoogleMapMeals
markers = {this.props.restaurants}
highlightedMarker = {this.props.highlightedMarker}
containerElement = {
<div
style = {{
flex: "0 0 400px",
height: "100vh",
position: "sticky",
top: "0"
}}
/>
}
mapElement = {
<div
style = {{
height: "100%",
width: "100%",
position: "absolute",
top: "0px",
left: "0px",
backgroundColor: "rgb(229, 227, 223)"
}}
/>
}
/>
);
}
}
@JulesCorb Ах, извините за это. Я обновил ответ.
Хорошо спасибо ! теперь он работает, но не решает мою проблему. Когда я наводю курсор на карту, она должна вызывать анимацию Bounce на соответствующем маркере, но на самом деле это не так.
@JulesCorb Анимация зависания работала раньше? Возможно, я неправильно понял ваш вопрос, но я думал, что проблема в том, что вся карта воссоздалась при каждом рендере.
извините, если я не понял! Да, анимация наведения работала раньше; но на самом деле проблема заключалась в том, что карта перерисовывалась каждый раз, когда на нее наводили курсор мыши. Например, если моя мышь находится на карте A, соответствующий маркер отскакивает от карты, а затем, когда я наведу указатель мыши на карту B, компонент карты полностью перерисовывается, и соответствующий маркер начинает отскакивать. Ищу решение для соответствующего маркера отскочить но без карты для рендеринга
@JulesCorb Все в порядке. Очень интересно. Возможно, уничтожение карты и создание совершенно новой решило проблему с анимацией маркера, если анимацию нельзя изменить после первоначального рендеринга. Может быть, key = {r._id + '?highlighted=' + (props.highlightedMarker === r._id)}
на Marker
подойдет.
Привет, @Tholle, большое спасибо за помощь. Я пытаюсь использовать ваше решение, но не могу получить доступ к
this.props.highlightedMarker
(11-я строка вашего примера кода в вашем ответе); Это дает мне неопределенность.