gribnoysup / react-yandex-maps

Yandex Maps API bindings for React
MIT License
327 stars 116 forks source link

React содержимое для balloon #27

Closed alexesDev closed 7 years ago

alexesDev commented 7 years ago

Жутко навелосипедил, но добился нужного поведения. Возможно все уже решено или есть более правильные пути?

Пример использования велосипеда...

<ActivePlacemark
  balloonContent={<div>Hello {this.state.time}</div>}
  ...
/>

components/active-placemark/index.js

import React from 'react';
import PropTypes from 'prop-types';
import ReactDOM from 'react-dom';
import { Placemark } from 'react-yandex-maps';

const makeLayout = (layoutFactory, component, contentKey) => {
  const Layout = layoutFactory.createClass('<div></div>', {
    build: function() {
      Layout.superclass.build.call(this);

      Layout.updateReactTree = () => ReactDOM.unstable_renderSubtreeIntoContainer(
        component,
        <div>{component.props[contentKey]}</div>,
        this.getElement().querySelector('div'),
      );

      Layout.updateReactTree();
    },
    clear: function() {
      Layout.updateReactTree = null;
      Layout.superclass.clear.call(this);
    },
  });

  return Layout;
};

class ActivePlacemark extends React.Component {
  static contextTypes = {
    ymaps: PropTypes.object.isRequired,
  };

  static propTypes = {
    balloonContent: PropTypes.node.isRequired,
  };

  constructor(props, context) {
    super(props);

    this.balloonLayout = makeLayout(
      context.ymaps.templateLayoutFactory, this, 'balloonContent');
  }

  componentDidUpdate(prevProps) {
    if (prevProps.balloonContent !== this.props.balloonContent) {
      if (this.balloonLayout.updateReactTree) {
        this.balloonLayout.updateReactTree();
      }
    }
  }

  render() {
    return (
      <Placemark
        {...this.props}
        options={{
          balloonContentLayout: this.balloonLayout,
          balloonPanelMaxMapArea: 0,
          ...this.props.options,
        }}
      />
    );
  }
}

export default ActivePlacemark;
gribnoysup commented 7 years ago

@alexesDev, привет! Готового решения в этой библиотеке нет, твой вариант выглядит очень даже неплохо :)

Я пока не уверен насчёт того как должно выглядеть АПИ для этого функционала, поэтому в эту библиотеку никаких готовых решений не добавлял

Ещё лейауты для маркеров и балунов поддерживаются в https://github.com/effrenus/yandex-map-react если интересно посмотреть как другие это делают

Я давно хотел добавить в документацию секцию Advanced, мне кажется твой пример туда мог бы войти. Хочешь сделать пулл-реквест? Если нет, не проблема, я чуть позже сам добавлю :)

alexesDev commented 7 years ago

В yandex-map-react как то все замудрено и размазано по файлам. Насчет моего примера не уверен насчет утечек памяти и нужно ли вызывать unmountComponentAtNode, к примеру, в clear. Пока пусть полежит, может получится все сделать изящней, пока обкатываю на более-менее production коде.

gribnoysup commented 7 years ago

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

EgorKluch commented 4 years ago

I use ReactDOM.portal for render balloon content on 'baloonopen' event. I havn't found find bugs yet. Who tried it? Any problems?

AndrewScottPH commented 3 years ago

I use ReactDOM.portal for render balloon content on 'baloonopen' event. I havn't found find bugs yet. Who tried it? Any problems?

Please, write how you do it

bannndi commented 2 years ago

I use ReactDOM.portal for render balloon content on 'baloonopen' event. I havn't found find bugs yet. Who tried it? Any problems?

Could you post some example ?