Covid 지도 - 반응 프로젝트 - 2일차

19641 단어 reactleafletproject
어제 저는 React, Leaflet.js 및 Open Disease Data API를 사용하여 프로젝트를 시작했습니다. 이 시리즈에서는 내가 하고 있는 일과 이 프로젝트를 만드는 동안 직면한 문제에 대해 쓰고 있습니다.
1 부:

2일차에 내가 한 일들:


  • 각 국가에 대한 disease.sh에서 가져온 데이터
  • GeoJSON으로 형식이 지정된 데이터
  • 기본 데이터가 포함된 팝업으로 국가별 마커 표시

  • 내가 만난 문제와 해결 방법:


    1. API에서 데이터를 저장하는 다른 접근 방식을 사용하고 싶었고 사용자 지정 useFetch 후크를 만들기로 결정했습니다.



    사용자 지정 후크를 빌드하는 동안 우리는 구성 요소 논리를 재사용 가능한 함수로 추출합니다. 그래서 커스텀 훅은 src 폴더에 별도의 파일에 넣어두고 사용부터 시작해야 하고 다른 훅을 호출할 수 있는 기능도 가지고 있습니다.

    useFetch 함수에서 URL을 매개변수로 전달하고 Fetch API와 함께 useState 및 useEffect를 사용하고 있습니다. App.js 또는 구성 요소 내부에서 데이터를 가져오는 것과 거의 동일합니다.

    이 함수는 API의 데이터, 로드 및 오류의 세 가지 요소를 반환합니다.

    //useFetch.js
    
    import { useState, useEffect } from 'react';
    
    const useFetch = (url) => {
        const [data, setData] = useState(null);
        const [loading, setLoading] = useState(false);
        const [error, setError] = useState(null);
    
        useEffect(() => {
           const fetchData = async () => {
            setLoading(true);
            try {            
                const res = await fetch(url);
                const json = await res.json();
                setData(json)          
                setLoading(false)
            } catch (error) {
              console.log(`Failed to fetch countries: ${error.message}`, error)
                setError(error)
            }
           };
           fetchData()
        }, [url])
        return { data, loading, error}
    }
    
    export default useFetch
    


    다음 단계는 Map.js 구성 요소에서 데이터, 로드 및 오류에 액세스하는 것입니다.

    //Map.js
    
    import useFetch from '../useFetch';
    
    const Mapt = () => {
      const url = 'https://disease.sh/v3/covid-19/countries'
        const { data, loading, error } = useFetch(url)
        console.log(data)    
    
        if (error) return <p>Error!</p>;
        if (loading) return <p>Loading...</p>;
      return (
          <MapContainer></MapContainer>
          )
    }
    export default Map
    


    지금은 아직 데이터를 사용하지 않습니다.

    2. 지도에 데이터를 표시하려면 데이터를 GeoJSON 형식으로 지정해야 했습니다.



    GeoJSON이란 무엇입니까?

    위키백과에서:

    GeoJSON is an open standard format designed for representing simple geographical features, along with their non-spatial attributes. It is based on the JSON format.



    Leaflet.js에서 GeoJSON의 예제 코드를 찾을 수 있습니다.

    // from Leaflet.js
    var geojsonFeature = {
        "type": "Feature",
        "properties": {
            "name": "Coors Field",
            "amenity": "Baseball Stadium",
            "popupContent": "This is where the Rockies play!"
        },
        "geometry": {
            "type": "Point",
            "coordinates": [-104.99404, 39.75621]
        }
    };
    


    이제 내 데이터로 동일한 작업을 수행해야 합니다. 처음에는 Map.js 파일에서 이 GeoJSON을 만들려고 했습니다. 그러나 나는 틀렸다. API에서 응답을 가져온 직후 useFetch 후크에서 수행해야 합니다.

    그래서 "FeatureCollection"유형의 geoJson 개체를 만들고 있습니다. API에는 수백 개의 배열이 포함되어 있기 때문에 이러한 기능에 액세스하려면 map()를 사용하여 모든 배열을 반복해야 합니다.

    // useFetch.js
    // ... 
    try {            
          const res = await fetch(url);
          const json = await res.json();
    
          const geoJson = {
              type: "FeatureCollection",
              features: json.map((country = {}) => {
              const { countryInfo = {}} = country;
              const { lat, long: lng} = countryInfo;
              return {
                   type: "Feature",
                   properties: {
                      ...country,
                  },
                   geometry: {
                      type: "Point",
                      coordinates: [lat, lng]
                  }
                }
               })
            }
              setData(geoJson)
              setLoading(false)
            } 
    // ...
    


    덕분에 속성과 좌표의 모든 데이터에 액세스할 수 있습니다. 위도(lat)와 경도(lng)의 쌍은 국가당 하나입니다.

    3. 이제 Map.js의 데이터에 액세스할 수 있습니다. 삼항 연산자를 사용하여 데이터가 있는지 확인하고 데이터가 있으면 마커와 팝업을 표시하고 그렇지 않으면 아무것도 표시하지 않아야 합니다.




    const Map = () => {
    // I won't be rewriting the whole code only the part in which I'm displaying the Markers
    // ...
    
    return (
    <MapContainer>
     {data ? data.features.map(country => {
       return (
        <Marker icon={redIcon} position={country.geometry.coordinates} key={country.properties.country}>
         <Popup>
           <h2>{country.properties.country}</h2>
           <p>Cases: {country.properties.cases}</p>
           <p>Deaths: {country.properties.deaths}</p>
           <p>Recovered: {country.properties.recovered}</p>
           <hr />
           <p>Cases Today: {country.properties.todayCases}</p>
           <p>Death Today: {country.properties.todayDeaths}</p>
           <p>Recovered Today: {country.properties.todayRecovered}</p>
            <hr />
            <p>Last Update: {country.properties.updated}</p>
          </Popup>
         </Marker>
            )
          })
        : null}
    </MapContainer>
    // ... 
    )
    }
    export default Map
    


    내 팝업이 깨끗하지 않다는 것을 알고 있습니다. 더 잘할 수 있습니다.

    현재 지도는 다음과 같습니다.


    다음 단계):


  • 팝업 부분의 리팩터링 코드
  • 국가 모양 및 색상 추가
  • 몇 가지 API에 대해 하나의 useFetch를 생성할 수 있는지 확인합니다
  • .

    좋은 웹페이지 즐겨찾기