Bing React JS 中的地图 - 道具更改时组件不加载
Bing Maps in React JS - Component doesn't Load when props change
我正在尝试使用道具在我的 React 应用程序上显示 bing 地图。地图在加载时正确显示,但当道具更改时,它不会重新加载地图组件。我知道问题是 componentDidMount() 只会在组件加载时被调用一次,但我不确定如何解决它。
interface IState {
addresses: Array<PropertyDetails>;
}
interface PropertyDetails {
fullAddress: string;
propertyNumber: number
}
export class Map extends React.Component<{ data }, IState> {
constructor(props) {
super();
this.state = {
addresses: []
};
}
getPropertyData() {
let propertyData: Array<PropertyDetails> = [];
let listProperties = this.props.data;
if (listProperties.length > 0) {
for (let i = 0; i < listProperties.length; i++) {
let address = listProperties[i].Streetnumber + " " +
listProperties[i].Streetname + " " +
listProperties[i].City + " " +
listProperties[i].State + " " +
listProperties[i].Zip;
var Property: PropertyDetails = {
fullAddress: address,
propertyNumber: listProperties[i].Propertyidentity
};
propertyData.push(Property);
}
}
this.setState({ addresses: propertyData })
}
loadBingMapScript() {
var BingMaps = document.getElementById("BingMaps");
if (BingMaps) {
document.body.removeChild(BingMaps);
}
(window as any).loadMapScenario = () => this.InitMap();
const script = document.createElement("script");
script.src = "https://www.bing.com/maps/sdk/mapcontrol?callback=loadMapScenario";
script.async = true;
script.defer = true;
script.id = "BingMaps";
document.body.appendChild(script);
}
componentDidMount() {
this.getPropertyData();
this.loadBingMapScript();
}
private InitMap(): void {
let mapElement: HTMLElement = this.refs.map as HTMLElement;
(window as any).ShowMap(mapElement, this.state.addresses);
}
public render() {
return <div>
<div style={{ height: "500px", width: "100%" }}>
<div id="map" ref="map"></div>
</div>
</div>
}
}
在上面的代码中,我在 componentDidMount() 中加载了 Bing 地图脚本,它在 Index.html 中调用了一个 JS 方法。但是当传递第二组道具时,它不会再次加载组件。所以地图不会刷新。
下面是index.html
function ShowMap(div, AddressList) {
var map = new Microsoft.Maps.Map(div, {
credentials: 'Key'
});
map.setView({
mapTypeId: Microsoft.Maps.MapTypeId.canvasLight,
center: new Microsoft.Maps.Location(39.828605, -98.579501),
zoom: 4,
customMapStyle: {
elements: {
area: { fillColor: '#b6e591' },
water: { fillColor: '#75cff0' },
tollRoad: { fillColor: '#a964f4', strokeColor: '#a964f4' },
arterialRoad: { fillColor: '#ffffff', strokeColor: '#d7dae7' },
road: { fillColor: '#ffa35a', strokeColor: '#ff9c4f' },
street: { fillColor: '#ffffff', strokeColor: '#ffffff' },
transit: { fillColor: '#000000' }
},
settings: {
landColor: '#efe9e1'
}
},
});
SearchMap(map, AddressList)
}
function SearchMap(map, addresses) {
for (let i = 0; i < addresses.length; i++) {
Microsoft.Maps.loadModule('Microsoft.Maps.Search', function () {
var searchManager = new Microsoft.Maps.Search.SearchManager(map);
var requestOptions = {
where: addresses[i].fullAddress,
callback: function (answer, userData) {
map.entities.push(new Microsoft.Maps.Pushpin(answer.results[0].location));
}
};
searchManager.geocode(requestOptions);
});
}
}
更新
我发现在 ComponentDidUpdate() 中再次加载地图确实在一定程度上解决了我的问题,但最终却出现了很多错误。所以我正在使用 React-Bing Maps npm 包。
我会用这种方法吗
componentDidUpdate (prevProps) {
if (this.props !== prevProps) {
// you can call your function here
// Try to not use setState in this area
// If you need to use, make sure to change only once
// using if conditions like if(this.state.once)... then set to false
}
}
这个解决方案有点奏效。它正在更新地图,但我也有一个问题。
componentDidUpdate(prevProps) {
if (this.props !== prevProps) {
this.getPropertyData();
this.loadBingMapScript();
}
}
我添加了上面的代码,但出现以下错误。
VM368 Log:1 Uncaught TypeError: Microsoft.Maps.NetworkCallbacks.f_logCallbackRequest is not a function
at VM100 Log:1
(anonymous) @ VM368 Log:1
3mapcontrol?callback=loadMapScenario:16 Uncaught TypeError: Cannot read property '0' of null
var Microsoft: any;
export class Home extends React.Component<RouteComponentProps<{}>, {}> {
constructor() {
super();
}
loadBingMapScript() {
var BingMaps = document.getElementById("BingMaps");
if (BingMaps) {
document.body.removeChild(BingMaps);
}
(window as any).loadMapScenario = () => this.InitMap();
const script = document.createElement("script");
script.src = "https://www.bing.com/maps/sdk/mapcontrol?callback=loadMapScenario";
script.async = true;
script.defer = true;
script.id = "BingMaps";
document.body.appendChild(script);
}
componentDidMount() {
this.loadBingMapScript();
}
private InitMap(): void {
Microsoft = (window as any).Microsoft;
if (Microsoft !== undefined) {
let mapElement: HTMLElement = this.refs.map as HTMLElement;
var map = new Microsoft.Maps.Map(mapElement, {
credentials: 'Credential',
center: new Microsoft.Maps.Location(39.393486, -98.100769),
zoom: 3
});
Microsoft.Maps.loadModule('Microsoft.Maps.Clustering', function () {
// Creating sample Pushpin data within map view
var pushpins = Microsoft.Maps.TestDataGenerator.getPushpins(1000, map.getBounds());
var clusterLayer = new Microsoft.Maps.ClusterLayer(pushpins, { gridSize: 100 });
map.layers.insert(clusterLayer);
});
}
}
public render() {
return <div>
<div style={{ height: "500px", width: "100%" }}>
<div id="map" ref="map" ></div>
</div>
</div>
}
}
我正在尝试使用道具在我的 React 应用程序上显示 bing 地图。地图在加载时正确显示,但当道具更改时,它不会重新加载地图组件。我知道问题是 componentDidMount() 只会在组件加载时被调用一次,但我不确定如何解决它。
interface IState {
addresses: Array<PropertyDetails>;
}
interface PropertyDetails {
fullAddress: string;
propertyNumber: number
}
export class Map extends React.Component<{ data }, IState> {
constructor(props) {
super();
this.state = {
addresses: []
};
}
getPropertyData() {
let propertyData: Array<PropertyDetails> = [];
let listProperties = this.props.data;
if (listProperties.length > 0) {
for (let i = 0; i < listProperties.length; i++) {
let address = listProperties[i].Streetnumber + " " +
listProperties[i].Streetname + " " +
listProperties[i].City + " " +
listProperties[i].State + " " +
listProperties[i].Zip;
var Property: PropertyDetails = {
fullAddress: address,
propertyNumber: listProperties[i].Propertyidentity
};
propertyData.push(Property);
}
}
this.setState({ addresses: propertyData })
}
loadBingMapScript() {
var BingMaps = document.getElementById("BingMaps");
if (BingMaps) {
document.body.removeChild(BingMaps);
}
(window as any).loadMapScenario = () => this.InitMap();
const script = document.createElement("script");
script.src = "https://www.bing.com/maps/sdk/mapcontrol?callback=loadMapScenario";
script.async = true;
script.defer = true;
script.id = "BingMaps";
document.body.appendChild(script);
}
componentDidMount() {
this.getPropertyData();
this.loadBingMapScript();
}
private InitMap(): void {
let mapElement: HTMLElement = this.refs.map as HTMLElement;
(window as any).ShowMap(mapElement, this.state.addresses);
}
public render() {
return <div>
<div style={{ height: "500px", width: "100%" }}>
<div id="map" ref="map"></div>
</div>
</div>
}
}
在上面的代码中,我在 componentDidMount() 中加载了 Bing 地图脚本,它在 Index.html 中调用了一个 JS 方法。但是当传递第二组道具时,它不会再次加载组件。所以地图不会刷新。
下面是index.html
function ShowMap(div, AddressList) {
var map = new Microsoft.Maps.Map(div, {
credentials: 'Key'
});
map.setView({
mapTypeId: Microsoft.Maps.MapTypeId.canvasLight,
center: new Microsoft.Maps.Location(39.828605, -98.579501),
zoom: 4,
customMapStyle: {
elements: {
area: { fillColor: '#b6e591' },
water: { fillColor: '#75cff0' },
tollRoad: { fillColor: '#a964f4', strokeColor: '#a964f4' },
arterialRoad: { fillColor: '#ffffff', strokeColor: '#d7dae7' },
road: { fillColor: '#ffa35a', strokeColor: '#ff9c4f' },
street: { fillColor: '#ffffff', strokeColor: '#ffffff' },
transit: { fillColor: '#000000' }
},
settings: {
landColor: '#efe9e1'
}
},
});
SearchMap(map, AddressList)
}
function SearchMap(map, addresses) {
for (let i = 0; i < addresses.length; i++) {
Microsoft.Maps.loadModule('Microsoft.Maps.Search', function () {
var searchManager = new Microsoft.Maps.Search.SearchManager(map);
var requestOptions = {
where: addresses[i].fullAddress,
callback: function (answer, userData) {
map.entities.push(new Microsoft.Maps.Pushpin(answer.results[0].location));
}
};
searchManager.geocode(requestOptions);
});
}
}
更新 我发现在 ComponentDidUpdate() 中再次加载地图确实在一定程度上解决了我的问题,但最终却出现了很多错误。所以我正在使用 React-Bing Maps npm 包。
我会用这种方法吗
componentDidUpdate (prevProps) {
if (this.props !== prevProps) {
// you can call your function here
// Try to not use setState in this area
// If you need to use, make sure to change only once
// using if conditions like if(this.state.once)... then set to false
}
}
这个解决方案有点奏效。它正在更新地图,但我也有一个问题。
componentDidUpdate(prevProps) {
if (this.props !== prevProps) {
this.getPropertyData();
this.loadBingMapScript();
}
}
我添加了上面的代码,但出现以下错误。
VM368 Log:1 Uncaught TypeError: Microsoft.Maps.NetworkCallbacks.f_logCallbackRequest is not a function
at VM100 Log:1
(anonymous) @ VM368 Log:1
3mapcontrol?callback=loadMapScenario:16 Uncaught TypeError: Cannot read property '0' of null
var Microsoft: any;
export class Home extends React.Component<RouteComponentProps<{}>, {}> {
constructor() {
super();
}
loadBingMapScript() {
var BingMaps = document.getElementById("BingMaps");
if (BingMaps) {
document.body.removeChild(BingMaps);
}
(window as any).loadMapScenario = () => this.InitMap();
const script = document.createElement("script");
script.src = "https://www.bing.com/maps/sdk/mapcontrol?callback=loadMapScenario";
script.async = true;
script.defer = true;
script.id = "BingMaps";
document.body.appendChild(script);
}
componentDidMount() {
this.loadBingMapScript();
}
private InitMap(): void {
Microsoft = (window as any).Microsoft;
if (Microsoft !== undefined) {
let mapElement: HTMLElement = this.refs.map as HTMLElement;
var map = new Microsoft.Maps.Map(mapElement, {
credentials: 'Credential',
center: new Microsoft.Maps.Location(39.393486, -98.100769),
zoom: 3
});
Microsoft.Maps.loadModule('Microsoft.Maps.Clustering', function () {
// Creating sample Pushpin data within map view
var pushpins = Microsoft.Maps.TestDataGenerator.getPushpins(1000, map.getBounds());
var clusterLayer = new Microsoft.Maps.ClusterLayer(pushpins, { gridSize: 100 });
map.layers.insert(clusterLayer);
});
}
}
public render() {
return <div>
<div style={{ height: "500px", width: "100%" }}>
<div id="map" ref="map" ></div>
</div>
</div>
}
}