ReactJS с Google Maps - отображение одного информационного окна в любое время

Я использую response-google-maps, и я могу отображать маркер и InfoWindow, которые работают правильно, но я хочу показать только текущее активное окно маркеров.

Я использую состояние isOpen, чтобы сохранить текущий маркер и показать, соответствует ли он текущему ключу, но он по-прежнему позволяет вам щелкать и переключать все информационные окна маркеров. Я подозреваю, что делаю очень простую ошибку, но я новичок в ReactJS. Также обратите внимание, что я нашел очень похожие вопросы, но ни один из них не помог мне решить эту проблему.

Вот мой код ..

    constructor(props){
    super(props);

    this.state = {
        isOpen: '',
    }

}

handleToggleOpen = (e) => {

   this.setState({
       isOpen: e
   });

   console.log(e);
   console.log('current state is... ');
   console.log(this.state.isOpen);
}

handleToggleClose = () => {
    this.setState({
        isOpen: null
    });
}

render() {

    // console.log(this.props.marker.id)

    return (

            <div>
        <Marker
            key={this.props.marker.id}
            position={{ lat: parseFloat(this.props.marker.acf.locations.lat), lng: parseFloat(this.props.marker.acf.locations.lng)}}
              icon={{
               url: this.props.icon,
               optimized: false,
               scaledSize: new google.maps.Size(25, 37),
             }}
             onClick={() =>  this.handleToggleOpen(this.props.marker.id)}
             audioPlay={this.props.audioPlay} >

                {
                        this.state.isOpen === this.props.marker.id && (
                     <InfoWindow onCloseClick={this.handleToggleClose}>
                        <div>
                         <h3 className="infowindow__title">{this.props.marker.title.rendered} {this.props.marker.acf.title_sub} </h3>
                         <span onClick={() =>this.refs.componentToDisplay.showPopup()} className="infowindow__link underline">Learn more</span>
                        </div>
                     </InfoWindow>)
                    }

            <PlacePopup ref="componentToDisplay" title={this.props.marker.title.rendered} intro={this.props.marker.acf.text} id={this.props.marker.id} subtitle={this.props.marker.acf.title_sub} audio={this.props.marker.acf.file} audioPlay={this.props.audioPlay}  >
                        </PlacePopup>
        </Marker> 
    </div>
        )
}

person jamessy    schedule 09.07.2018    source источник


Ответы (1)


Поскольку каждый из ваших маркеров имеет собственное состояние, вам нужно будет найти способ соединить каждый объект состояния каждого компонента маркера. Причина, по которой вам может понадобиться состояние каждого маркера, заключается в том, что при щелчке по одному из маркеров он должен уведомлять все другие маркеры о том, что был нажат маркер, поэтому, если у них есть открытые окна, они должны немедленно закрыть его. В этом случае я бы предложил решить эту проблему с помощью Redux (поскольку вы сказали, что все еще новичок в React, я не совсем уверен, знакомы ли вы с Redux или нет, поэтому, если вы это сделаете, пожалуйста, сообщите мне комментарии, и я постараюсь помочь предоставить решение с использованием Redux). Я считаю, что вам все еще удастся решить проблему без помощи Redux, однако в будущем она может стать действительно сложной и трудно управляемой.

Кроме того, в вашем коде есть пара вещей, которые, я думаю, нужно сначала исправить. Было бы гораздо лучше, если бы isOpen внутри вашего состояния был установлен как логическое значение, а не как строка. Итак, вот изменения, которые вы должны внести в свой код:

  1. В вашем конструкторе инициализируйте isOpen:

    this.state = {isOpen: false}

  2. Внутри вашей функции handleToggleOpen нет необходимости передавать какие-либо параметры, поэтому вы можете удалить e:

    handleToggleOpen = () => {this.setState ({isOpen:! this.state.isOpen}); }

По сути, это и есть переключение, поэтому вы также можете удалить свою handleToggleClose функцию (поскольку handleToggleOpen обрабатывает как открытие, так и закрытие), а затем заменить ее на handleToggleOpen внутри вашей функции рендеринга.

  1. Теперь вам нужно только изменить

this.state.isOpen === this.props.marker.id &&

просто

this.state.isOpen &&

тогда он должен работать так, как должен, без необходимости каждый раз сравнивать идентификатор каждого маркера.

person aboudicheng    schedule 13.07.2018
comment
Спасибо за столь блестящие объяснения. Я очень ценю объяснение того, почему текущий код не работает, и улучшения моего кода. У меня уже настроен Redux, поэтому я собираюсь реализовать его сам, в основном потому, что думаю, что узнаю больше, практикуясь. Спасибо - person jamessy; 16.07.2018