Reputation: 1626
in my reactjs app, I'm using Redux, Redux-Thunk.In my component using google-maps
, I want to implement center_changed
using Markers.so whenever i move the marker latlng and address also will change. when im saving state component getting refresh.so i want to stop rendering my component using shouldComponentUpdate
. but when i was returning false
from shouldComponentUpdate
then also map getting refresh.
my component
class StepTwo extends React.Component{
constructor(props){
super(props);
this.state={
pickupConfirmButton:false,
dropoffConfirmButton:false,
}
this.mapLoaded = false;
this.map=false;
this.pickMarker=false;
this.pickIcon = '';
this.dropMarker=false;
this.dropIcon='';
}
componentWillReceiveProps(props){
if (props.isScriptLoadSucceed) {
this.mapLoaded= true;
this.directionsService = new google.maps.DirectionsService();
this.directionsDisplay = new google.maps.DirectionsRenderer({ suppressMarkers: true });
this.map = new google.maps.Map(document.getElementById('map'), {
zoom: 14,
center: { lat: 17.3850, lng: 78.4867 },
mapTypeControl: false,
streetViewControl: false,
gestureHandling:'greedy',
});
this.pickMarker = new google.maps.Marker ({
icon:this.pickIcon,
map: this.map,
animation: google.maps.Animation.DROP,
position: { lat: 17.3850, lng: 78.4867 },
// draggable: true
});
this.dropIcon = {
path: 'M 0,0 C -2,-20 -10,-22 -10,-30 A 10,10 0 1,1 10,-30 C 10,-22 2,-20 0,0 z M -2,-30 a 2,2 0 1,1 4,0 2,2 0 1,1 -4,0',
fillColor: '#00E64D',
fillOpacity: 1,
strokeColor: '#000',
strokeWeight: 1,
scale: 1,
};
this.pickMarker.addListener('click', () =>{
this.pickupMarkerClickListener();
});
}
}
shouldComponentUpdate(nextProps, nextState) {
if (this.props.pickupAddress || nextProps.pickupAddress) {
//after return false also i'm unable to stop rendering
//component
return false;
}
}
pickupMarkerClickListener = () =>{
if(this.dropMarker){
this.dropMarker.setVisible(false);
}
this.directionsDisplay.set('directions', null);
this.map.setCenter(this.pickMarker.getPosition());
this.map.setZoom(18);
this.map.addListener('center_changed', () => {
let lat=this.map.getCenter().lat();
let lng=this.map.getCenter().lng();
let pickLatlng ={lat:lat,lng:lng};
//on below function when i want to send latlng to redux state component getting refresh.
// this.props.pickupHandler(pickLatlng);
let geocoder = new google.maps.Geocoder;
geocoder.geocode({'location': {lat:lat,lng:lng}}, (results, status) =>{
if (status === 'OK') {
////////////////////////////////////////////////////////
//////// this is function which getting refresh/////////
///////////////////////////////////////////////////////
this.props.pickupAddHandler(results[0].formatted_address);
}
})
this.pickMarker.setPosition({lat:lat,lng:lng});
})
}
render(){
return(
<Row type="flex" justify="space-around" align="middle" className='stepTwo'>
<Col lg={{span:10}} className="form" >
<Input
className='input'
placeholder='Enter Pick-up Locaiton'
id='pick'
ref="pickupInput"
onChange={this.pickupSearch}
// value={this.props.pickupAddress}
/>
<div style={{padding:'1rem'}} align='center'>
<Button><Icon type="swap" className="swapIcon" /> </Button><span style={{fontSize:'0.8rem'}}>*Reverse Location</span>
</div>
<Input
className='input'
placeholder='Enter Drop-off Locaiton'
ref="dropoffInput"
onChange={this.dropoffSearch}
/>
</Col>
<Col lg={{span:13}}>
<div id="map" className='map'></div>
{this.state.pickupConfirmButton && <Button className="cnfrmBtn" size="large" onClick={this.pickupMaker}>Confirm Location</Button> }
{this.state.dropoffConfirmButton && <Button className="cnfrmBtn" size="large" onClick={this.dropoffMaker}>Confirm Location</Button> }
</Col>
</Row>
)
}
}
const StepTwoLoadedMap = scriptLoader(
[config.MapApi]
)(StepTwo);
const mapStateToProps = (state) =>{
console.log(state.StepTwoReducer.pickupLatlng,'mapState')
return{
pickupAddress:state.StepTwoReducer.pickupAddress,
pickupLocation:state.StepTwoReducer.pickupLatlng
}
}
export default connect(mapStateToProps,{validationS2,pickupAddHandler,pickupHandler,dropoffHandler})(StepTwoLoadedMap);
ActionCreator
export function pickupAddHandler(address){
return function(dispatch){
dispatch({type:PICKUPADD,payload:address})
}
}
export function pickupHandler(latlng) {
return function(dispatch) {
dispatch({ type: PICKUP_LATLNG,payload:latlng });
};
}
Reducer.js
import {VALIDS2,PICKUPADD,PICKUP_LATLNG} from '../actions/types';
const INITIAL_STATE = {
validStepTwo:false,
pickupAddress:null,
pickupLatlng:false,
};
export default (state=INITIAL_STATE,action) => {
// console.log(action,'step two')
switch(action.type) {
case PICKUPADD:
return {...state,pickupAddress:action.payload}
case PICKUP_LATLNG:
return {...state,pickupLatlng:action.payload}
case VALIDS2:
return {...state,validStepTwo:action.payload};
default:
return state;
}
}
how can I store address and latlng on redux state when center_changed
, without rendering component.
another problem is when i change center of the map i will get address, that address I'm storing pickupAddress
state if we stop rendering component, there is input field so I want to show that address as input field value, if component not re-render then how can i show current address inside input field.
some reasons i don't want to use any library
anyone can please help me how can store redux state without rendering but it should show the updated value inside input fields or any other simple method,i'm stuck since 1 week!plzzzzzz
Upvotes: 0
Views: 609
Reputation: 11257
Always try to create a container component for third party libraries(google map in this case) and Always return false in shouldComponentUpdate lifecycle method. Sample code to give context of its use.
// GoogleMapComponent.jsx
import React, { Component } from 'react'
export default class GoogleMap extends Component {
shouldComponentUpdate() {
return false;
}
componentDidMount() {
this.map = new google.maps.Map( this.refs.map, {
center: {lat: this.props.lat, lng: this.props.lng},
zoom: 5
})
}
componentWillReceiveProps(nextProps) {
this.map.panTo({ lat: nextPros.lat, lng: nextPros.lng });
}
render() {
return (
<div id="googleMap" ref="map" />
)
}
}
// App.jsx
import GoogleMap from './GoogleMapComponent'
import React, { Component } from 'react'
export default class App extends Component {
constructor(props) {
super(props);
this.state = {lat: 30.397, lng: 130.876};
}
render() {
return (
<div style={{ height: '100%'}} >
<button onClick={() => this.seState({ lat:50.712, lng: -30.08 }) }>
Your Favourite Place
</button>
<GoogleMap
lat={this.state.lat}
lng={this.state.lng}
/>
</div>
)
}
}
This may not be the perfect answer to your problem, but will surely improve the structure of code and help resolve the issue. Hope that helps!!
Upvotes: 1