渲染Map
之后,我创建了对API的一系列调用,并根据结果构造了Rectangles
。然后,我根据用户希望看到的比例来更改Rectangle
的颜色。使用香草js,这很容易,因为我只保留了所有Rectangles
的引用并更新了color属性。但是使用react-leaflet
时,我看不到做相同事情的方法。
HTML(此处为Leaflet CSS)
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Leaflet CSS -->
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.3.4/dist/leaflet.css" integrity="sha512-puBpdR0798OZvTTbP4A8Ix/l+A4dHDD0DGqYW6RQ+9jxkRFclaxxQb/SJAWZfWAkuyeQUytO7+7N4QKrDh+drA==" crossorigin="" />
<!-- Bootstrap CSS-->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
<!-- Fullscreen plugin CSS-->
<link href='https://api.mapbox.com/mapbox.js/plugins/leaflet-fullscreen/v1.0.1/leaflet.fullscreen.css' rel='stylesheet' crossorigin="anonymous" />
</head>
<body>
<div id='app'></div>
<script src="https://code.jquery.com/jquery-3.3.1.min.js" integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script>
</body>
</html>
Index.js
import React from 'react';
import ReactDom from 'react-dom';
import App from './components/App';
const appContainer = document.getElementById('app');
ReactDom.render(<App />, appContainer);
App.js(对于本演示来说是不必要的,但稍后会添加更多内容)
import React from 'react';
import MapController from './MapController';
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
value: '',
};
}
render() {
return (
<MapController />
);
}
}
export default App;
MapController.js-用于添加功能的Map组件的包装器
import React from 'react';
import {
Map, ImageOverlay,
} from 'react-leaflet';
import { CRS } from 'leaflet';
import '../lib/leaflet-fullscreen';
componentDidMount() {
//After the map renders, start calling the API to create triangles
this.createColorCodedPriceOverlays();
}
async createColorCodedPriceOverlays() {
const pageSize = 100;
let startingIndex = 0;
const apiCalls = [];
// Need to get the first batch to determine how many listings exist
// getListings will update the Map on state and return a promise that
// resolves to the total number of records that exist
const total = await this.getListings(startingIndex);
// Create the calls needed to get all parcels for sale
while (startingIndex <= total) {
startingIndex += pageSize;
apiCalls.push(this.getListings(startingIndex));
}
Promise.all(apiCalls);
}
//Call api and create batch of Rectangles from the results
async getListings(startingIndex) {
const response = await fetch('www.foobarApi.io/batchx');
const json = await response.json();
const { parcels, total } = json.data;
let price = (parcels[0] && parcels[0].publication) ?parcels[0].publication.price : undefined;
const parcelRectangles = [];
let rect;
let i = 0;
parcels.forEach((parcel) => {
price = parcel.publication.price;
//Create the <Rectangle
//Simplified, usually dynamically set color
rect = (<Rectangle bounds={[[0,0],[100,100]]} color="white" />)
parcelRectangles.push(rect);
i += 1;
});
//Set the generated Rectangles on the State so I can get them later
this.setState((prevState) => {
const allParcels = prevState.parcels ? [...prevState.parcels, ...parcelRectangles] : parcelRectangles;
const totalParcelsRetrieved = prevState.totalParcelsRetrieved + parcelRectangles.length;
return { parcels: allParcels, totalParcelsRetrieved };
});
return total;
}
onValueChange(event) {
/ **
* So now the user changed some values and I want to alter
* the color property of the <Rectangles> I have stored in
* the state. But I don't have anyway of doing this.
*/
}
render() {
return (
<div className="container-fluid">
<div className="row map-row">
<Map
center={[0, 0]}
zoom={3}
crs={L.CRS.Simple}
minZoom={1}
maxZoom={10}
bounds={[[-150.5, -150.5], [150.5, 150.5]]}
maxBounds={[[-150.5, -150.5], [150.5, 150.5]]}
maxBoundsViscosity={2.0}
fullscreenControl
attributionControl={false}
style={{ height: '100%', width: '100%' }}
>
//Stored Rectangles on the state to try and update them later
{this.state.parcels}
</Map>
<UserControlsComponent onValueChange={this.onValueChange.bind(this)}/>
</div>
</div>
);
}
答案 0 :(得分:1)
我会建议通过状态管理矩形属性,而不是保留对矩形实例的引用。假设矩形数组的初始数据以以下格式表示:
[
{
name: "Rectangle 1",
color: "white",
bounds: [[10., 0.0], [20.0, 15.0]]
},
//...
]
和以下组件用于呈现矩形列表:
const RectangleList = ({ data }) => {
return (
<span>
{data.map((item, i) => {
return <Rectangle key={i} bounds={item.bounds} color={item.color} />;
})}
</span>
);
}
然后下面的示例演示如何在外部事件上修改矩形颜色:
class MapExample extends Component {
constructor(props) {
super(props);
this.state = {
items: items
};
this.handleClick = this.handleClick.bind(this);
}
handleClick(){
const items = [...this.state.items];
items[0].color = "red";
this.setState({ items: items });
}
render() {
return (
<div>
<button onClick={this.handleClick}>Change color</button>
<Map center={this.props.center} zoom={this.props.zoom}>
<TileLayer url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png" />
<RectangleList data={items} />
</Map>
</div>
);
}
}
答案 1 :(得分:0)
我没有保留Rectangle
中的this.state.parcels
组件并试图直接对其进行更新,而是必须保留每个Rectangle
的参数,并在更改调用this.state.setState({rectangelProps})
的参数时使用新属性呈现每个Rectangle
。我没有意识到setState
每次都叫render
。