我使用的是库反应谷歌地图,我想在两个节点之间使用DirectionsRenderer。这是我的状态
this.state={
currentPosition:{lat: 26.84 ,lng: 75.80},
destinationPosition:{lat: 26.84 ,lng: 75.80},
};
我想显示当前位置和标记之间的方向。我的componentDidMount((在render方法中。以下是渲染方法的代码
class map extends React.PureComponent{
constructor(props){
super(props);
this.state={
currentPosition:{lat: 26.84 ,lng: 75.80},
destinationPosition:{lat: 26.84 ,lng: 75.80},
direction:false
};
}
onMarkerPositionChanged(e){
this.setState((state)=>({
destinationPosition:{lat:e.latLng.lat(),lng:e.latLng.lng()}}));
}
handleClick(){
if(navigator.geolocation){
navigator.geolocation.getCurrentPosition((position)=>{
this.setState(()=>({
currentPosition:{lat:position.coords.latitude,lng:position.coords.longitude}}))
});
}
else{
alert("Geoloaction is not supported by your browser");
}
}
changeDir(){
if(this.state.direction)
this.setState(()=>({direction:false}))
else
this.setState(()=>({direction:true}))
}
render(){
const MyMapComponent = compose(
withProps({
googleMapURL: "https://maps.googleapis.com/maps/api/js?key=AIzaSyC5VMMlyr_A6K5ycpOrq3OsVM8YYbn0q3A&v=3.exp&libraries=geometry,drawing,places",
loadingElement: <div style={{ height: `100%` }} />,
containerElement: <div style={{ height: `300px` }} />,
mapElement: <div style={{ height: `100%` }} />,
}),
withScriptjs,
withGoogleMap,
lifecycle({
componentDidMount() {
const google=window.google;
console.log(this.state);
//--->this statement prints null
const DirectionsService = new google.maps.DirectionsService();
DirectionsService.route({
origin: new google.maps.LatLng(this.state.currentPosition.lat, this.state.currentPosition.lng),
destination: new google.maps.LatLng(this.state.destinationPosition.lat,this.state.destinationPosition.lng),
//----> this is where i want to use the state to get the direction between //current location and marker
travelMode: google.maps.TravelMode.DRIVING,
}, (result, status) => {
if (status === google.maps.DirectionsStatus.OK) {
this.setState({
directions: result,
});
} else {
console.error(`error fetching directions ${result}`);
}
});
}
})
)(
props =>
<GoogleMap defaultZoom={15} defaultCenter={this.state.destinationPosition} >
<Marker position={this.state.destinationPosition} draggable changeLat
onDragEnd={this.onMarkerPositionChanged.bind(this)}
/>
<Marker
icon="https://www.robotwoods.com/dev/misc/bluecircle.png"
position={this.state.currentPosition}
/>
{this.state.direction && props.directions && <DirectionsRenderer directions={props.directions} />}
<Button bsStyle="success" onClick={this.handleClick.bind(this)}>Current Position</Button>
<Button bsStyle="success" onClick={this.changeDir.bind(this)}>Get Direction</Button>
</GoogleMap>
);
return(
<Container state={this.state} map={MyMapComponent}/>
);
}
}
export default map;
当我用常数值代替起点和终点时,效果很好。
首先,将组件的名称map
更改为Map
。请阅读此SO帖子。
现在,关于这个:
当我使用常量代替起点和终点时,它工作得很好。
这个问题的答案有背景,请继续阅读以下内容,以便更清楚。
this
上下文的问题
在代码中,您有一个map
组件,您可以使用this
访问它的任何属性(包括状态(。例如,如果在render
函数内调用this.state
,则会得到map
的状态。例如,您可以使用map
组件的componentDidMount
函数在状态中设置一个值,如下所示:
class map extends Component {
constructor(props){
this.state = { myVal: 1}
}
componentDidMount(){
this.setState({ myVal: 2})
}
}
这段代码不会失败,因为componentDidMount是组件的React函数,this
可以在组件内部使用,因为它在同一上下文中。在这种情况下,this.setState
将设置map
的状态,因为this
是map
。
这是您提供的示例代码:
const { compose, withProps, lifecycle } = require("recompose"); const { withScriptjs, withGoogleMap, GoogleMap, DirectionsRenderer, } = require("react-google-maps");
const MapWithADirectionsRenderer = compose( withProps({
googleMapURL: "https://maps.googleapis.com/maps/api/js?key=AIzaSyC4R6AN7SmujjPUIGKdyao2Kqitzr1kiRg&v=3.exp&libraries=geometry,drawing,places",
loadingElement: <div style={{ height: `100%` }} />,
containerElement: <div style={{ height: `400px` }} />,
mapElement: <div style={{ height: `100%` }} />, }), withScriptjs, withGoogleMap, lifecycle({
componentDidMount() {
const DirectionsService = new google.maps.DirectionsService();
DirectionsService.route({
origin: new google.maps.LatLng(41.8507300, -87.6512600),
destination: new google.maps.LatLng(41.8525800, -87.6514100),
travelMode: google.maps.TravelMode.DRIVING,
}, (result, status) => {
if (status === google.maps.DirectionsStatus.OK) {
this.setState({
directions: result,
});
} else {
console.error(`error fetching directions ${result}`);
}
});
} }) )(props => <GoogleMap
defaultZoom={7}
defaultCenter={new google.maps.LatLng(41.8507300, -87.6512600)}
>
{props.directions && <DirectionsRenderer directions={props.directions} />} </GoogleMap> );
<MapWithADirectionsRenderer />
在本例中,this.setState
指的是MapWithADirectionsRenderer
的上下文,因此this.setState
正在设置MapWithADirectionsRenderer
的状态,因为this
是MapWithADirectionsRenderer
。
现在,在您的代码中,您将创建一个名为MyMapComponent
的新组件作为const对象。该组件允许您定义该新组件的componentDidMount
函数。这个新组件将有自己的上下文,所以当您在MyMapComponent
组件中写入this
时,它将引用MyMapComponent
,而不是map
。
您不能像那样从MyMapComponent
中访问map
的状态,您必须将props传递给MyMapComponent
。
解决方案
我创建了几个关于如何传递值的示例。
解决方案1
您可以创建一个任何名称的道具(在本例中,它被称为测试,值为My value
(:
const MyMapComponent = compose(
withProps({
googleMapURL:
"https://maps.googleapis.com/maps/api/js?key=AIzaSyC5VMMlyr_A6K5ycpOrq3OsVM8YYbn0q3A&v=3.exp&libraries=geometry,drawing,places",
loadingElement: <div style={{ height: `100%` }} />,
containerElement: <div style={{ height: `400px` }} />,
mapElement: <div style={{ height: `100%` }} />,
test:'My value'
}),
lifecycle({
componentDidMount() {
console.log(JSON.stringify(this.props.test));
}
}),
withScriptjs,
withGoogleMap,
)(props => (
<GoogleMap defaultZoom={8} defaultCenter={{ lat: -34.397, lng: 150.644 }}>
{props.isMarkerShown && (
<Marker position={{ lat: -34.397, lng: 150.644 }} />
)}
</GoogleMap>
));
通过这种方式,您可以使用给定的值记录this.props.test
,无论您使用什么。
解决方案2
如果您需要根据在Map
状态中找到的值来渲染组件,请使用类似的方法。
您可以将道具传递给MyMapComponent
,然后使用props.
访问它们并添加道具的名称。
例如,如果您传递一个名为latProp
的新道具,如下所示:
<MyMapComponent isMarkerShown latProp={-34.397} />
你可以这样访问它:
(props => (
<GoogleMap defaultZoom={8} defaultCenter={{ lat: -34.397, lng: 150.644 }}>
{props.isMarkerShown && (
<Marker position={{ lat: props.latProp, lng: 150.644 }} />
)}
</GoogleMap>
));
由于您想要的是用状态中的属性替换常数值,因此只需将props.latProp
中发送的值替换为状态中的任何属性即可:
<MyMapComponent isMarkerShown latProp={this.state.lat} />
这是完整的组件:
const MyMapComponent = compose(
withProps({
googleMapURL:
"https://maps.googleapis.com/maps/api/js?key=AIzaSyC5VMMlyr_A6K5ycpOrq3OsVM8YYbn0q3A&v=3.exp&libraries=geometry,drawing,places",
loadingElement: <div style={{ height: `100%` }} />,
containerElement: <div style={{ height: `400px` }} />,
mapElement: <div style={{ height: `100%` }} />,
}),
withScriptjs,
withGoogleMap,
)(props => (
<GoogleMap defaultZoom={8} defaultCenter={{ lat: -34.397, lng: 150.644 }}>
{props.isMarkerShown && (
<Marker position={{ lat: props.latProp, lng: props.lngProp }} />
)}
</GoogleMap>
));
class App extends Component{
constructor(props){
super(props);
this.state = { lat: -34.400, lng: 151.644 }
}
render(){
return (
<div>
<MyMapComponent isMarkerShown latProp={this.state.lat} lngProp={this.state.lng} />
</div>
);
}
}
export default App;