【问题标题】:Data on Leaflet JS map not showing up correctlyLeaflet JS 地图上的数据未正确显示
【发布时间】:2021-01-11 07:22:16
【问题描述】:

我正在 React 中构建一个 Corona Virus 跟踪器,它在 Choropleth Leaflet Map 上显示数据。我有一个 data.json 文件,其中包含用于绘制此地图边界的多边形数据。这个想法是,将来自 API 的 COVID 数据添加到这个 data.json 文件,返回这个对象,并将它作为一个道具传递给地图组件。在地图组件中,在地图中的 GeoJSON 组件中的每个要素上执行 countryLoad 函数。这会根据 COVID 病例的数量显示每个国家/地区颜色编码的 COVID 数据。问题是,有时数据无法正确加载,地图显示为灰色。

我尝试了很多方法,包括添加一个超时,使它在 80% 的时间里都可以正常工作,但有时仍然无法正常工作。

World.js 文件:

import React, { useState, useEffect } from "react";
import "./App.css";
import {
    Card,
    CardContent,
} from "@material-ui/core";

import Table from "./Table";
import { sortData} from "./Helper";
import Map from "./Map";
import { features } from "./data/countries.json";
import "leaflet/dist/leaflet.css";

const World = () => {

    const [countries, setCountries] = useState([]);
    const [mapCountries, setMapCountries] = useState([]);
    const [tableData, setTableData] = useState([]);
    const [casesType, setCasesType] = useState("cases");
    const [mapZoom, setMapZoom] = useState(3);
     
    
    

    const attachCovidData = () => {   //Attach covid data to newFeatures
        const newFeatures = [];

        for (let i = 0; i < features.length; i++) {
            newFeatures.push(features[i]);
        }

        for (let i = 0; i < newFeatures.length; i++) {
            const featureCountry = newFeatures[i];
            featureCountry.cases = 0;
            featureCountry.casesText = "";
            const covidCountry = tableData.find(
                (country) =>
                    country.countryInfo.iso3 === featureCountry.properties.ISO_A3
            );
            if (covidCountry != null) {
                let cases = covidCountry.cases;
                let deaths = covidCountry.deaths;
                featureCountry.cases = cases;
                featureCountry.opacityLevel = 0;
                if (featureCountry.cases < 50000) {
                    featureCountry.opacityLevel = 0.1;
                } else if (featureCountry.cases < 50000) {
                    featureCountry.opacityLevel = 0.2;
                } else if (
                    featureCountry.cases >= 50000 &&
                    featureCountry.cases < 100000
                ) {
                    featureCountry.opacityLevel = 0.3;
                } else if (
                    featureCountry.cases >= 100000 &&
                    featureCountry.cases < 250000
                ) {
                    featureCountry.opacityLevel = 0.4;
                } else if (
                    featureCountry.cases >= 250000 &&
                    featureCountry.cases < 500000
                ) {
                    featureCountry.opacityLevel = 0.5;
                } else if (
                    featureCountry.cases >= 500000 &&
                    featureCountry.cases < 1000000
                ) {
                    featureCountry.opacityLevel = 0.6;
                } else {
                    featureCountry.opacityLevel = 1;
                }
                featureCountry.deaths = deaths;
                featureCountry.casesText = "";
            }
        }
        console.log(newFeatures);
        return newFeatures;
    };



    useEffect(() => {
        const getCountriesData = async () => {
            fetch("https://disease.sh/v3/covid-19/countries")   // Get covid data
                .then((response) => response.json())
                .then((data) => {
                    const countries = data.map((country) => ({
                        name: country.country,
                        value: country.countryInfo.iso2,
                    }));
                    let sortedData = sortData(data);
                    setCountries(countries);

                    setMapCountries(data);
                    setTableData(sortedData);
                });
        };

        getCountriesData();
    }, []);



    return (
        <div className="app">
            <div className="app__left">
                <div className="app__header">
                    <h1>World Overview</h1>
                </div>
                <Map
                    countries={mapCountries}
                    casesType={casesType}
                    center={{ lat: 34.80746, lng: -40.4796 }}
                    zoom={mapZoom}
                    newFeatures={attachCovidData()}
                />
            </div>
            <Card style = {{marginTop: '50px'}} className="app__right">
                <CardContent>
                    <div className="app__information">
                        <h3>Total Cases</h3>
                        <Table countries={tableData} />
                    </div>
                </CardContent>
            </Card>
        </div>
    );
};

export default World;

Map.js 文件

import React, { useState, useEffect } from "react";
import { MapContainer as LeafletMap, TileLayer, GeoJSON } from "react-leaflet";
import "./Map.css";
import "leaflet/dist/leaflet.css";

function Map({ countries, center, zoom, newFeatures }) {
    const [loadedMap, setLoadedMap] = useState(false);
    useEffect(() => {
        setTimeout(() => {
            setLoadedMap(true);
        }, 1000);
    }, []);
    
    const countryLoad= (country, layer) => {
        
            const name = country.properties.ADMIN;
            const confirmedCases = country.cases;
            const confirmedCasesCommas = confirmedCases
                .toString()
                .replace(/\B(?=(\d{3})+(?!\d))/g, ",");

            const confirmedDeaths = country.deaths;
            const opacityLevel = country.opacityLevel;
            console.log(confirmedCases);
            layer.options.fillColor = `rgba(0,0,255, ${country.opacityLevel}`;
            layer.bindPopup(`${name} ${confirmedCasesCommas} `);
        
    
    };
    console.log(newFeatures);

    const map = (
        <div className="map">
            <LeafletMap center={center} zoom={zoom}>
                <TileLayer
                    url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
                    attribution='&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
                />
                <GeoJSON
                    data={newFeatures}
                    style={{ weight: 0.7 }}
                    onEachFeature={countryLoad}
                />
            </LeafletMap>
            {console.log(countries)}
        </div>
    );


    
    

    return loadedMap?map:null;
}

export default Map;

【问题讨论】:

  • 有时数据无法正确加载”是什么意思
  • 对不起,我应该澄清一下。每个国家/地区都显示为灰色,而不是紫色阴影,较深的阴影代表更多的 covid 病例。因此,在某些情况下,作为道具发送到地图文件的数据并不准确

标签: javascript reactjs api leaflet


【解决方案1】:

问题似乎在于在从端点获取实际数据之前进行渲染。

只有在端点返回数据后,您才需要将const [loadedMap, setLoadedMap] = useState(false); 逻辑移动到World 组件并设置标志为true

所以用

包裹地图渲染(World组件中
{Boolean(mapCountries.length) && (<Map
    countries = { mapCountries }
    casesType = { casesType }
    center = {{ lat: 34.80746, lng: -40.4796 }}
    zoom = { mapZoom }
    newFeatures = { attachCovidData() }
/>)}

并从Map 组件中删除整个loadedMap

【讨论】:

    猜你喜欢
    • 2020-10-07
    • 2021-11-02
    • 2022-01-14
    • 2017-01-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-17
    • 2014-07-15
    相关资源
    最近更新 更多