我正在尝试从这里实现 GeoJSON 示例:https://uber.github.io/react-map-gl/#/Examples/geo但是当我尝试逐年更改年份滑块时,数据和数据层保持不变,根本没有改变。
我复制了相同的代码并集成到我的“create-react-app”中,地图的渲染方式与示例中相同,但数据保持静态并拒绝从控制面板更改。
有人可以告诉我我错过了什么吗?
我的代码是这样的:
const MAPBOX_TOKEN =
"pk.eyJ1IjoiZnN5bHFhIiwiYSI6ImNrNXp2enFmMzAxbDAzb21iemMxN2dqY2MifQ.TvYAgClf77WIygyRg_Sa4Q"; // Set your mapbox token here
export default class GeoApp extends Component {
state = {
year: 2015,
data: null,
hoveredFeature: null,
viewport: {
latitude: 40,
longitude: -100,
zoom: 3,
bearing: 0,
pitch: 0
}
};
componentDidMount() {
requestJson(
"https://raw.githubusercontent.com/uber/react-map-gl/master/examples/.data/us-income.geojson",
(error, response) => {
if (!error) {
this._loadData(response);
console.log(response);
}
}
);
}
_loadData = data => {
updatePercentiles(data, f => f.properties.income[this.state.year]);
this.setState({ data });
};
_updateSettings = (name, value) => {
console.log(`name:${name}, value:${value}`);
if (name === "year") {
this.setState({ year: value });
const { data } = this.state;
if (data) {
console.log("data before", data);
updatePercentiles(data, f => f.properties.income[value]);
console.log("data after", data);
// trigger update
this.setState({ data: { ...data } });
}
console.log("data", data);
}
};
_onViewportChange = viewport => this.setState({ viewport });
_onHover = event => {
const {
features,
srcEvent: { offsetX, offsetY }
} = event;
const hoveredFeature =
features && features.find(f => f.layer.id === "data");
this.setState({ hoveredFeature, x: offsetX, y: offsetY });
};
_renderTooltip() {
const { hoveredFeature, x, y } = this.state;
return (
hoveredFeature && (
<div className="tooltipi" style={{ left: x, top: y }}>
<div>State: {hoveredFeature.properties.name}</div>
<div>Median Household Income: {hoveredFeature.properties.value}</div>
<div>
Percentile: {(hoveredFeature.properties.percentile / 8) * 100}
</div>
</div>
)
);
}
render() {
const { viewport, data } = this.state;
return (
<div style={{ height: "100%" }}>
<MapGL
{...viewport}
width="50%"
height="50%"
mapStyle="mapbox://styles/mapbox/light-v9"
onViewportChange={this._onViewportChange}
mapboxApiAccessToken={MAPBOX_TOKEN}
onHover={this._onHover}
>
<Source type="geojson" data={data}>
<Layer {...dataLayer} />
</Source>
{console.log("layers", dataLayer)}
{this._renderTooltip()}
</MapGL>
<ControlPanel
containerComponent={this.props.containerComponent}
settings={this.state}
onChange={this._updateSettings}
/>
</div>
);
}
}
export function RenderToDom(container) {
render(<GeoApp />, container);
}
updatePercentelies 函数是这样的:
import { range } from "d3-array";
import { scaleQuantile } from "d3-scale";
export function updatePercentiles(featureCollection, accessor) {
const { features } = featureCollection;
const scale = scaleQuantile()
.domain(features.map(accessor))
.range(range(9));
features.forEach(f => {
const value = accessor(f);
f.properties.value = value;
f.properties.percentile = scale(value);
});
}
在react-map-gl的GitHub页面上,有人解释说
<Source>
是一个PureComponent。第一次渲染后,除非 props 发生浅层变化,否则它不会更新,即 oldValue !== newValue。当您改变 JSON 数据时,它仍然是同一个对象,因此 React 不会检测到更改。
我在尝试传递保存在 React 状态中的 geoJSON 对象时遇到了完全相同的问题。解决该问题的解决方案是设置不同的键并强制重新渲染
<Source>
组件:
import React, { useState } from 'react';
import Map, { Source } from 'react-map-gl';
const MyMap = () => {
const [geojson, setGeojson] = useState(initialGeojson);
const [key, setKey] = useState(0);
// Function to update GeoJSON
const updateGeojson = (newGeojson) => {
setGeojson(newGeojson);
setKey(key + 1); // Increment key to force re-render
};
return (
<Map {...viewport}>
<Source id="my-data" type="geojson" data={geojson} key={key}>
{/* Add your layers here */}
</Source>
</Map>
);
};
或者您也可以使用像
uuid
这样的包为每次重新渲染生成随机密钥。