问题
how can i get asynchronous reducers data ,i search but didn't get solution
Booking component
cutPick = () => {
this.props.pickup(false);
}
action creator
export function pickup(latlng) {
return function (dispatch) {
dispatch({type:PICKUP_STATE,payload:latlng});
}
}
reducer
import {PICKUP_STATE} from '../actions/types';
export default function (state={},action) {
switch(action.type) {
case PICKUP_STATE:
return {...state,pickup:action.payload}
}
return state;
}
Map component
import React from 'react';
import scriptLoader from "react-async-script-loader";
import config from '../../../config'
import 'antd/dist/antd.css';
import { Icon,Button,Alert,Row, Col} from 'antd';
import {connect} from "react-redux";
import * as actions from "../actions";
class Map extends React.Component{
constructor(props){
super(props);
this.state = {
pick:false,
drop:false,
mapCenter : { lat: 17.3850, lng: 78.4867 },
pickupConfirmButton:false,
dropoffConfirmButton:false
};
this.map=false;
this.directionsService =false;
this.directionsDisplay = false;
this.mapLoaded = false;
this.pickMarker=false;
this.dropMarker=false;
}
//listen map current location event and set marker and pick state
addYourLocationButton = (map) => {
this.pickMarker = new google.maps.Marker ({
map: this.map,
animation: google.maps.Animation.DROP,
position: this.state.pick ? this.state.pick : this.state.mapCenter,
draggable: true
});
if(!this.mapLoaded) {
return false;
}
var controlDiv = document.createElement('div');
let firstChild = document.createElement('button');
firstChild.style.backgroundColor = '#fff';
firstChild.style.border = 'none';
firstChild.style.outline = 'none';
firstChild.style.width = '28px';
firstChild.style.height = '28px';
firstChild.style.borderRadius = '2px';
firstChild.style.boxShadow = '0 1px 4px rgba(0,0,0,0.3)';
firstChild.style.cursor = 'pointer';
firstChild.style.marginRight = '10px';
firstChild.style.padding = '0px';
firstChild.title = 'Your Location';
controlDiv.appendChild(firstChild);
let secondChild = document.createElement('div');
secondChild.style.margin = '5px';
secondChild.style.width = '18px';
secondChild.style.height = '18px';
secondChild.style.backgroundImage = 'url(https://maps.gstatic.com/tactile/mylocation/mylocation-sprite-1x.png)';
secondChild.style.backgroundSize = '180px 18px';
secondChild.style.backgroundPosition = '0px 0px';
secondChild.style.backgroundRepeat = 'no-repeat';
secondChild.id = 'you_location_img';
firstChild.appendChild(secondChild);
// google.maps.event.addListener(map, 'dragend', () => {
// document.getElementById("you_location_img").style.backgroundPosition='0px 0px';
// });
google.maps.event.addListener(this.pickMarker, 'dragend', () =>{
let lat=this.pickMarker.getPosition().lat();
let lng=this.pickMarker.getPosition().lng();
this.setState({pick:{lat:lat,lng:lng}},function () {
let geocoder = new google.maps.Geocoder;
geocoder.geocode({'location': {lat:lat,lng:lng}}, function(results, status) {
if (status === 'OK') {
document.getElementById('pick').value = results[0].formatted_address;
}
})
// console.log(this.state.pick);
})
if (this.state.pick && this.state.drop){
this.calculateRoute();
}
});
firstChild.addEventListener('click', () => {
let imgX = '0';
let animationInterval = setInterval( () =>{
if (imgX == '-18') imgX = '0';
else imgX = '-18';
document.getElementById("you_location_img").style.backgroundPosition=imgX + 'px 0px';
}, 500);
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition( (position) => {
let latlng = new google.maps.LatLng(position.coords.latitude, position.coords.longitude);
let geocoder = new google.maps.Geocoder;
geocoder.geocode({'location': latlng}, function(results, status) {
if (status === 'OK') {
document.getElementById('pick').value = results[0].formatted_address;
}
})
if(latlng){
this.setState(()=>({
pick:latlng
}))
}
this.pickMarker.setPosition(latlng);
map.setCenter(latlng);
if (this.state.pick && this.state.drop){
this.calculateRoute();
}
clearInterval(animationInterval);
document.getElementById("you_location_img").style.backgroundPosition='-144px 0px';
});
}
else {
clearInterval(animationInterval);
document.getElementById("you_location_img").style.backgroundPosition='0px 0px';
}
});
controlDiv.index = 1;
map.controls[google.maps.ControlPosition.RIGHT_BOTTOM].push(controlDiv);
}
//load gmaps ,load maps and directions and set center as user current location
componentWillReceiveProps({isScriptLoadSucceed}){
if (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: 11,
center: this.state.mapCenter
});
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition( (position)=> {
let initialLocation = new google.maps.LatLng(position.coords.latitude, position.coords.longitude);
// console.log(this.state.mapCenter)
this.setState({mapCenter:initialLocation} , ()=> {
// console.log(this.state.mapCenter)
})
this.map.setCenter(initialLocation);
});
}else{
console.log('error in current location')
}
this.directionsDisplay.setMap(this.map);
//icon of current location in map and current loc pickup marker
this.addYourLocationButton(this.map);
//listener for pickup marker when it clicked
this.pickMarker.addListener('click', () =>{
this.pickupMarkerClickListener();
});
}
else{
alert("Something went wrong, plz check internet Connection")
}
}
//for Refs
componentDidMount() {
this.props.onRef(this);
}
//for Refs
componentWillUnmount() {
this.props.onRef(null);
}
// this function pick state false when user click on cut pick address from pickup field and set direction false also
isPickEmpty=(emptyPickState)=>{
console.log(this.props.pickupProps);
this.setState({pick:emptyPickState},function () {
this.pickMarker.setMap(null);
this.directionsDisplay.set('directions', null);
//sending false as distance to BookingDetails
this.props.routeCalc(false);
});
};
//it handle search hint of google place api (getting data from Booking Form)
pickupSearch =(pickupAddress) =>{
let options = {
types: [],
componentRestrictions: {
'country': 'IN'
}
};
let inputPick = document.getElementById('pick');
const autocompletePick = new google.maps.places.Autocomplete(inputPick, options);
autocompletePick.bindTo('bounds', this.map);
google.maps.event.addListener(autocompletePick, 'place_changed', () => {
let place =autocompletePick.getPlace();
let lat = place.geometry.location.lat(),
lng = place.geometry.location.lng();
let geocoder = new google.maps.Geocoder;
geocoder.geocode({'location': {lat:lat,lng:lng}}, function(results, status) {
if (status === 'OK') {
document.getElementById('pick').value = results[0].formatted_address;
}
});
this.pickUp({lat:lat,lng:lng})
});
}
//this function put pick marker on pickup search
pickUp = (pick) => {
// console.log(pick)
if(this.pickMarker){
this.pickMarker.setMap(null);
}
this.setState({pick:pick}, () => {
// console.log(this.state.pick);
var infoWindow = new google.maps.InfoWindow;
this.pickMarker = new google.maps.Marker({
map:this.map,
animation: google.maps.Animation.DROP,
position: this.state.pick,
draggable: true
});
infoWindow.setPosition(this.state.pick);
// infoWindow.setContent('Location found.');
// infoWindow.open(this.map);
this.map.setCenter(this.state.pick);
this.pickMarker.addListener('click', () =>{
this.pickupMarkerClickListener();
});
google.maps.event.addListener(this.pickMarker, 'dragend', () =>{
this.pickupMarkerDragListener();
});
this.focus.scrollIntoView();
})
if (this.state.pick && this.state.drop){
this.calculateRoute();
}
};
//this function invoke click and drag function of pickup marker
pickupMaker=()=>{
this.setState({pickupConfirmButton:false});
this.map.setZoom(11);
if(this.pickMarker){
this.pickMarker.setMap(null);
}
google.maps.event.clearListeners(this.map, 'center_changed');
this.pickMarker = new google.maps.Marker ({
map: this.map,
animation: google.maps.Animation.DROP,
position: this.state.pick,
draggable:true
});
if(this.dropMarker){
this.dropMarker.setVisible(true);
}
//listening on drag of pick marker
google.maps.event.addListener(this.pickMarker, 'dragend', () => {
this.pickupMarkerDragListener();
console.log('marker')
});
//listening on click of pick marker
this.pickMarker.addListener('click', () =>{
this.pickupMarkerClickListener();
});
//if both state are set the calculate the root
if (this.state.pick && this.state.drop){
this.calculateRoute();
}
};
//this function handle click event of pick Marker
pickupMarkerClickListener = () => {
if(this.dropMarker){
this.dropMarker.setVisible(false);
}
this.directionsDisplay.set('directions', null);
this.setState({pickupConfirmButton:true});
this.map.setCenter(this.pickMarker.getPosition());
this.map.setZoom(16);
this.map.addListener('center_changed', () => {
let lat=this.map.getCenter().lat();
let lng=this.map.getCenter().lng();
this.setState({pick:{lat:lat,lng:lng}},function () {
let geocoder = new google.maps.Geocoder;
geocoder.geocode({'location': {lat:lat,lng:lng}}, function(results, status) {
if (status === 'OK') {
document.getElementById('pick').value = results[0].formatted_address;
}
})
// console.log(this.state.pick);
});
this.pickMarker.setPosition({lat:lat,lng:lng});
// console.log(this.map.getCenter().lat(),this.map.getCenter().lng(),this.pickMarker.getPosition())
});
};
//This function Handle drage event of pick marker
pickupMarkerDragListener = () => {
console.log('dragged');
let lat=this.pickMarker.getPosition().lat();
let lng=this.pickMarker.getPosition().lng();
this.setState({pick:{lat:lat,lng:lng}}, () => {
let geocoder = new google.maps.Geocoder;
geocoder.geocode({'location': {lat:lat,lng:lng}}, (results, status) => {
if (status === 'OK') {
document.getElementById('pick').value = results[0].formatted_address;
}
})
console.log(this.state.pick);
})
if ((this.state.pick && this.state.drop) && (this.state.pickupConfirmButton === false && this.state.dropoffConfirmButton ===false)){
this.calculateRoute();
}
}
// this function drop state false when user click on cut drop address from dropoff field and set direction false also
isDropEmpty=(emptyDropState)=>{
// console.log(emptyPickState);
// console.log(this.state.pick);
this.setState({drop:emptyDropState},function () {
// this.pickMarker=false;
this.dropMarker.setMap(null);
this.directionsDisplay.set('directions', null);
//sending false as distance to BookingDetails
this.props.routeCalc(false);
});
};
//it handle drop search hint of google place api (getting data from Booking Form)
dropoffSearch = (dropoffSearch) =>{
let options = {
types: [],
componentRestrictions: {
'country': 'IN'
}
};
const autocompleteDrop = new google.maps.places.Autocomplete(document.getElementById('drop'), options);
autocompleteDrop.bindTo('bounds', this.map);
google.maps.event.addListener(autocompleteDrop, 'place_changed', () => {
let place =autocompleteDrop.getPlace();
let lat = place.geometry.location.lat(),
lng = place.geometry.location.lng();
// this.props.dropHandler({lat:lat,lng:lng})
//
// this.setState({drop:place.name});
// let lat = place.geometry.location.lat(),
// lng = place.geometry.location.lng();
//putting place in pick field
let geocoder = new google.maps.Geocoder;
geocoder.geocode({'location': {lat:lat,lng:lng}}, function(results, status) {
if (status === 'OK') {
// console.log(results[0].formatted_address)
document.getElementById('drop').value = results[0].formatted_address;
}
});
this.dropOff({lat:lat,lng:lng})
});
};
//this function put drop marker on dropoff search(function invoked from Booking Details)
dropOff = (drop) => {
if (this.dropMarker){
this.dropMarker.setMap(null);
}
this.setState({drop:drop}, () => {
// console.log(this.state.drop);
var infoWindow = new google.maps.InfoWindow;
this.dropMarker = new google.maps.Marker({
map:this.map,
animation: google.maps.Animation.DROP,
position: this.state.drop,
draggable: true
});
infoWindow.setPosition(this.state.drop);
// infoWindow.setContent('Location found.');
// infoWindow.open(this.map);
this.map.setCenter(this.state.drop);
// console.log(this.state.drop);
google.maps.event.addListener(this.dropMarker, 'dragend', () =>{
this.dropoffMarkerDragListener();
});
this.dropMarker.addListener('click', () =>{
this.dropoffMarkerClickListener();
});
if (this.state.pick && this.state.drop){
this.calculateRoute();
}
this.focus.scrollIntoView();
})
// if (this.state.pick && this.state.drop){
// this.calculateRoute();
// }
};
//this function invoke click and drag function of drop marker
dropoffMaker= () =>{
this.setState({dropoffConfirmButton:false});
this.map.setZoom(11);
this.dropMarker.setMap(null);
google.maps.event.clearListeners(this.map, 'center_changed');
this.dropMarker = new google.maps.Marker ({
map: this.map,
animation: google.maps.Animation.DROP,
position: this.state.drop,
draggable: true
});
if(this.pickMarker){
this.pickMarker.setVisible(true);
}
google.maps.event.addListener(this.dropMarker, 'dragend', () =>{
this.dropoffMarkerDragListener();
});
this.dropMarker.addListener('click', () =>{
this.dropoffMarkerClickListener();
});
if (this.state.pick && this.state.drop){
this.calculateRoute();
}
}
//this function handle click event of Drop Marker
dropoffMarkerClickListener=()=>{
this.pickMarker.setVisible(false);
this.directionsDisplay.set('directions', null);
this.setState({dropoffConfirmButton:true});
this.map.setCenter(this.dropMarker.getPosition());
this.map.setZoom(16);
this.map.addListener('center_changed', () => {
let lat=this.map.getCenter().lat();
let lng=this.map.getCenter().lng();
this.setState({drop:{lat:lat,lng:lng}},function () {
let geocoder = new google.maps.Geocoder;
geocoder.geocode({'location': {lat:lat,lng:lng}}, function(results, status) {
if (status === 'OK') {
document.getElementById('drop').value = results[0].formatted_address;
}
});
});
this.dropMarker.setPosition({lat:lat,lng:lng});
console.log(this.map.getCenter().lat(),this.map.getCenter().lng(),this.dropMarker.getPosition())
});
}
//This function Handle drage event of drop marker
dropoffMarkerDragListener= () => {
let lat=this.dropMarker.getPosition().lat();
let lng=this.dropMarker.getPosition().lng();
this.setState({drop:{lat:lat,lng:lng}},function () {
let geocoder = new google.maps.Geocoder;
geocoder.geocode({'location': {lat:lat,lng:lng}}, function(results, status) {
if (status === 'OK') {
document.getElementById('drop').value = results[0].formatted_address;
}
})
console.log(this.state.drop);
})
if ((this.state.pick && this.state.drop) && (this.state.pickupConfirmButton === false && this.state.dropoffConfirmButton ===false)){
this.calculateRoute();
}
};
//this function set direction and calculate the root of pick and drop
calculateRoute = () =>{
var request ={
origin:this.state.pick,
destination:this.state.drop,
travelMode:"DRIVING"
};
this.directionsService.route(request,(result,status) => {
if(status== "OK"){
console.log(result.routes[0].legs[0].distance);
this.props.routeCalc(result.routes[0].legs[0].distance);
this.directionsDisplay.setDirections(result);
}
});
};
render(){
return(
<div className="Map" ref={node => this.focus = node}>
<Alert
message="Tap or Drag Marker[s] to set exact location Then Click on Confirm Location"
type="info"
showIcon
/>
<div id="map" style={{height: "500px"}}></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> }
</div>
)
}
}
function mapStateToProps (state) {
return {pickupProps:state.BookingData.pickup}
}
// export default Map;
const ScriptLoadedMap = scriptLoader(
[config.MapApi]
)(Map);
export default connect(mapStateToProps,actions)(ScriptLoadedMap);
i'm sending false value from Booking to action creator then i'm dispatching and storing value in action in reducer
but when i'm calling pickupProps from Map component first time i'm getting undefined after first time getting false value.
so here my problem is how can i get first time (asynchronous) false value when it called from Booking component.
来源:https://stackoverflow.com/questions/50406252/first-time-getting-undefined-props-from-mapstatetoprops