Mateusz
Mateusz

Reputation: 1193

React+Redux - show InfoWindow on Marker click

I would like to display InfoWindow on Marker click. I followed some tutorials and I used react-google-maps for my project. I would like my app to work like this: "https://tomchentw.github.io/react-google-maps/basics/pop-up-window" but my code is a little bit different.

class Map extends React.Component {

  handleMarkerClick(){
    console.log("Clicked");
  }

  handleMarkerClose(){
    console.log("CLOSE");
  }
    render(){
      const mapContainer= <div style={{height:'100%',width:'100%'}}></div>

      //fetch markers
      const markers = this.props.markers.map((marker,i) => {
        return (
            <Marker key={i} position={marker.location} showTime={false} time={marker.time} onClick={this.handleMarkerClick} >
            {
              <InfoWindow onCloseClick={this.handleMarkerClose}>
                 <div>{marker.time}</div>
              </InfoWindow>
            }
            </Marker>
          )
      })

      /* set center equals to last marker's position */
      var centerPos;
      if(markers[markers.length-1]!== undefined)
      {
        centerPos=markers[markers.length-1].props.position;
      }
      else {
        centerPos={};
      }




        return (
          <GoogleMapLoader
          containerElement={mapContainer}
          googleMapElement={
            <GoogleMap
              defaultZoom={17}
              center={centerPos}
            >
              {markers}
            </GoogleMap>
          }/>
        );
    }
}

export default Map;

I got "this.props.markers" from another class component, which fetching data from URL. I am almost sure, that it is easy problem to solve. Currently on marker click in console I got "Clicked" and on Marker close "CLOSE" as you can guess from above code it is because of handleMarkerClick() and handleMarkerClose(). I want to have pop-window with InfoWindow. What should I do to make it work?

Here is heroku link : App on heroku

Upvotes: 0

Views: 1096

Answers (1)

Shubham Jain
Shubham Jain

Reputation: 930

Hi I came across the same requirement. I did this (I am using redux and redux-thunk) :

GoogleMap.js

import React, { Component } from 'react';
import { connect } from 'react-redux';
import {
    withGoogleMap,
    GoogleMap,
    Marker,
    InfoWindow
} from 'react-google-maps';
import { onMarkerClose } from '../actions/Cabs';


const GettingStartedGoogleMap = withGoogleMap(props => (
    <GoogleMap
        defaultZoom={12}
        defaultCenter={{ lat: 12.9716, lng: 77.5946 }}
    >
        {props.markers.map( (marker, index) => (
            <Marker {...marker} onClick={() => props.onMarkerClose(marker.key)}>
                {marker.showInfo &&(
                    <InfoWindow onCloseClick={() => props.onMarkerClose(marker.key)}>
                        <div>
                            <h1>Popover Window</h1>
                        </div>
                    </InfoWindow>
                )}
            </Marker>
        ))}
    </GoogleMap>
));

class CabType extends Component{

    constructor(props){
        super(props);
    }
    render(){
        if(this.props.cabs.length === 0){
            return <div>loading...</div>
        }
        return(
            <div className="map-wrapper">
                <GettingStartedGoogleMap
                    containerElement={
                        <div style={{ height: '100%' }} />
                    }
                    mapElement={
                        <div style={{ height: '100%' }} />
                    }
                    onMarkerClose = {this.props.onMarkerClose}
                    markers={this.props.showMap ? this.props.markers : []}
                />
            </div>
        )
    }
}

export default connect(store => {return {
    cabs : store.cabs,
    markers: store.markers
}}, {
    onMarkerClose
})(CabType);

Action.js

const getMarkers = (cabs , name) => dispatch => {

    let markers = [];
    let data = {};

    cabs.map(cab => {
        if(cab.showMap){
            data = {
                position: {
                    lat : cab.currentPosition.latitude,
                    lng : cab.currentPosition.longitude
                },
                showInfo: false,
                key: cab.cabName,
                icon: "/images/car-top.png",
                driver: cab.driver,
                contact: cab.driverContact,
            };
            markers.push(data);
        }
    });
      dispatch(emitMarker(markers));
    };

function emitSetMarker(payload){
    return{
        type: SET_MARKER,
        payload
    }
}

export const onMarkerClose = (key) => dispatch => {
    dispatch(emitSetMarker(key))
};

RootReducer.js

import { combineReducers } from 'redux';
import { cabs } from "./Cabs";
import { markers } from "./Markers";

const rootReducer = combineReducers({
    cabs,
    markers,
});

export default rootReducer;

MarkerReducer.js

import { GET_MARKERS, SET_MARKER } from "../types"

export const markers = (state = [], action) => {
    switch (action.type){
        case GET_MARKERS:
            return action.payload;
        case SET_MARKER:
            let newMarker = state.map(m => {
                if(m.key === action.payload){
                    m.showInfo = !m.showInfo;
                }
                return m;
            });
            return newMarker;
        default: return state;
    }
};

Sorry for a long post but this is code which is tested and running. Cheers!

Upvotes: 1

Related Questions