Лучший способ получить данные для компонента боковой панели из useeffect

avatar
swade77
8 августа 2021 в 21:14
191
0
0

Я работаю над приложением React, которое использует mapbox-gl и реагирует на создание карты мира, на которой при нажатии на страну отображается боковая панель с информацией о валюте. Я создал карту, которая при нажатии находит данные из контекста, но я не могу найти правильный способ передать эту информацию компоненту боковой панели. Должен ли я использовать другой контекст для хранения данных и отправки компоненту в файле app.js или должна быть боковая панель в файле map.js, который я использую для создания карты и использования useRef для хранения информации вне useEffect или должен ли map.js быть компонентом класса (я использую это приложение для изучения хуков реакции)? Я хочу, чтобы боковая панель появлялась только при нажатии на страну на карте и не была видна при первоначальном рендеринге. Я знаю, что это много, но у меня кружится голова. Спасибо Map.js

import React, { useRef, useEffect, useContext, useState } from "react";
import './Map.css'
import mapboxgl from "mapbox-gl";
import { MapContext } from '../store/MapContext';
import findCountryIndex from '../store/FindCountryIndex';




mapboxgl.accessToken = process.env.REACT_APP_MAPBOX_API_KEY;

const MapboxGLMap = () => {
  const map = useRef(null);
  const mapContainer = useRef(null);
  const lng = -32.87393;
  const lat = 43.6439;
  const zoom = 2;
  const maxZoom = 10;


  //Country Data State

  const countryData = useContext(MapContext);
 
  useEffect(() => { 
        if (map.current) return;
        map.current = new mapboxgl.Map({
        container: mapContainer.current,
        style: "mapbox://styles/chriswade112358/ckpro4ivq05yh17sec15y3js0",
        center: [lng, lat],
        zoom: zoom,
        minZoom: zoom,
        maxZoom: maxZoom,
        });
        let hoveredCountryId = null;

        map.current.on("style.load", function () {
        map.current.addLayer({
            id: "country-fills",
            type: "fill",
            source: "composite",
            "source-layer": "country_boundaries",
            layout: {},
            paint: {
            "fill-color": "#079432",
            "fill-opacity": [
                "case",
                ["boolean", ["feature-state", "hover"], false],
                0.33,
                0.0,
            ],
            },
        });

        map.current.on("mousemove", "country-fills", function (e) {
            const cfeatures = map.current.queryRenderedFeatures(e.point, {
            layers: ["country-boundaries"],
            });
            if (hoveredCountryId) {
                map.current.setFeatureState(
                {
                    source: "composite",
                    sourceLayer: "country_boundaries",
                    id: hoveredCountryId,
                },
                {
                    hover: false,
                }
                );
            }
            hoveredCountryId = cfeatures[0].id;
            map.current.setFeatureState(
                {
                source: "composite",
                sourceLayer: "country_boundaries",
                id: hoveredCountryId,
                },
                { hover: true }
            );
            
        });

        map.current.on("mouseleave", "country-fills", function () {
            if (hoveredCountryId) {
            map.current.setFeatureState(
                {
                source: "composite",
                sourceLayer: "country_boundaries",
                id: hoveredCountryId,
                },
                { hover: false }
            );
            }
            hoveredCountryId = null;
        });

        map.current.on("click", function (e) {
            const features = map.current.queryRenderedFeatures(e.point, {
            layers: ["country-boundaries"],
            });
            
            if (features[0]) {
                let countryIndex = findCountryIndex(features[0].properties.iso_3166_1_alpha_3, countryData[0]);
                const data = countryData[0][countryIndex]
                console.log(data)
                    
            }
             
        });
    });
  });
  return (
    <div>
        <div ref={mapContainer} className="map-container" />
    </div>
  );
};

export default MapboxGLMap;

MapContext.js

mport React, { useState, createContext, useEffect } from 'react';
import customData from './customData.json';
import axios from 'axios';
import Loading from '../Loading/Loading';





export const MapContext = createContext();


export const CountryDataProvider = props => {
    const [cData] = useState(customData);
    const [apiData, setApiData] = useState();
    const [countryData, setCountryData] = useState([]);
    useEffect(() => {
        async function fetchData(){
            const baseURL = 'http://api.currencylayer.com/';
            const key = `?access_key=${process.env.REACT_APP_CURRENCY_API_KEY}`;
            const { data: { timestamp, source, quotes } }  = await axios.get(`${baseURL}live${key}`)
            const quoteData = Object.entries(quotes)
            quoteData.forEach(quote => {
                let key = quote[0]
                let alteredKey = key.slice(3,6)
                quote[0] = alteredKey
            })
            setApiData({timestamp, source, quoteData});
        }
        fetchData();
        
        
    }, [])

    if(apiData === undefined){
        <>
        console.log("should be loading")
        <Loading />
        </>
    }
    else{
       cData.forEach(country => {
            let rateArray = [];
            let apiQuote = apiData.quoteData //array of arrays;
            for(let i=0; i < country.currCode.length; i++){
                for(let j=0; j < apiQuote.length; j++){
                    if(country.currCode[i] === apiQuote[j][0]){
                        rateArray.push(apiQuote[j][1])
                    }   
                }
            }
            let countryDataObject = {
                "alpha3Code": country.alpha3Code,
                "name": country.name,
                "currName": country.currName,
                "currCode": country.currCode,
                "exchangeRate": rateArray,
                "currSymbol": country.currSymbol,
                "pegged": country.pegged,
                "territory": country.territory,
                "flag": country.flag
            }
            countryData.push(countryDataObject);          
       }) 
    }
    
    
    
    return <MapContext.Provider value={[countryData, setCountryData]}>{props.children}</MapContext.Provider>;
    
}

MapSidebar.js

import './MapSidebar.css'


const MapSidebar = (sideBarData) => {
    console.log(sideBarData)
    return (
       <div className="Sidebar">
           <h1>Hey!</h1>
       </div>
        
        
    );
};

export default MapSidebar;
Источник

Ответы (0)