SearchMapPriceLabel handles price formatting and shouldComponentUpdate check (avoid long refresh batches on top of map)

This commit is contained in:
Vesa Luusua 2017-08-15 11:32:56 +03:00
parent 3cf201b273
commit 7a6ac4506f
2 changed files with 50 additions and 26 deletions

View file

@ -4,6 +4,8 @@
position: relative;
width: auto;
height: auto;
border: 0;
padding: 0;
}
.priceLabel {

View file

@ -1,7 +1,10 @@
import React, { PropTypes } from 'react';
import React, { Component, PropTypes } from 'react';
import { OverlayView } from 'react-google-maps';
import { injectIntl, intlShape } from 'react-intl';
import classNames from 'classnames';
import * as propTypes from '../../util/propTypes';
import { formatMoney } from '../../util/currency';
import config from '../../config';
import css from './SearchMapPriceLabel.css';
@ -11,43 +14,62 @@ const getPixelPositionOffset = (width, height) => {
return { x: -1 * (width / 2), y: -1 * (height + 3) };
};
const SearchMapPriceLabel = props => {
const { className, rootClassName, price, listing } = props;
const geolocation = listing.attributes.geolocation;
class SearchMapPriceLabel extends Component {
shouldComponentUpdate(nextProps) {
const { listing: currentListing } = this.props;
const { listing: nextListing } = nextProps;
const isSameListing = currentListing.id.uuid === nextListing.id.uuid;
const hasSamePrice = currentListing.attributes.price === nextListing.attributes.price;
return !(isSameListing && hasSamePrice);
}
// Explicit type change to object literal for Google OverlayViews (geolocation is SDK type)
const latLngLiteral = { lat: geolocation.lat, lng: geolocation.lng };
const classes = classNames(rootClassName || css.root, className);
render() {
const { className, rootClassName, intl, listing, onListingClicked } = this.props;
const geolocation = listing.attributes.geolocation;
return (
<OverlayView
position={latLngLiteral}
mapPaneName={OverlayView.OVERLAY_MOUSE_TARGET}
getPixelPositionOffset={getPixelPositionOffset}
>
<div className={classes}>
<div className={css.caretShadow} />
<div className={css.priceLabel}>
{price}
</div>
<div className={css.caret} />
</div>
</OverlayView>
);
};
// Create formatted price if currency is known or alternatively show just the unknown currency.
const price = listing.attributes.price;
const formattedPrice = price && price.currency === config.currencyConfig.currency
? formatMoney(intl, config.currencyConfig, price)
: price.currency;
// Explicit type change to object literal for Google OverlayViews (geolocation is SDK type)
const latLngLiteral = { lat: geolocation.lat, lng: geolocation.lng };
const classes = classNames(rootClassName || css.root, className);
return (
<OverlayView
position={latLngLiteral}
mapPaneName={OverlayView.OVERLAY_MOUSE_TARGET}
getPixelPositionOffset={getPixelPositionOffset}
>
<button className={classes} onClick={() => onListingClicked(listing)}>
<div className={css.caretShadow} />
<div className={css.priceLabel}>
{formattedPrice}
</div>
<div className={css.caret} />
</button>
</OverlayView>
);
}
}
SearchMapPriceLabel.defaultProps = {
className: null,
rootClassName: null,
};
const { string } = PropTypes;
const { func, string } = PropTypes;
SearchMapPriceLabel.propTypes = {
className: string,
rootClassName: string,
listing: propTypes.listing.isRequired,
price: string.isRequired,
onListingClicked: func.isRequired,
// from injectIntl
intl: intlShape.isRequired,
};
export default SearchMapPriceLabel;
export default injectIntl(SearchMapPriceLabel);