Search code examples
reactjscsvleafletreact-leaflet

ReactJS-Leaflet: upload csv file in leaflet


here I have a question regarding references to creating a feature in the react leaflet.

So, the feature has the following functions =

  1. The user page when they want to upload a location is in the form of a csv file containing latitude and longitude.

enter image description here

  1. When the user clicks the red button above, a popup will appear to upload the csv file.

enter image description here

  1. When finished uploading the csv file, it will go directly to the location based on latitude and longitude.

enter image description here

So my question is, does anyone have a tutorial on how to create a csv upload button that points directly to a map with reactjs and leaflets? Thank you very much


Solution

  • Although you have not asked to use react-leaflet I would advise you to do so because you will end up in a mess when you will have to export the map reference to reuse it across places.

    First create a button that will handle the upload of a csv file. There is a really useful guide to do so without the use of libraries like paparse although it simplifies a lot this procedure. Next you need to transform the csv columns to some form of data to use. This is also included in the guide. You end up with an array of csv columns.

    Then all you need to do is to create a custom react-leaflet component to render the markers and zoom to the markers viewport.

    Also you can clean the csv file once you insert a new one.

    function App() {
      const [csvToArray, setCsvToArray] = useState([]);
    
      const fileReader = new FileReader();
    
      const csvFileToArray = (string) => {
        const csvHeader = string.slice(0, string.indexOf("\n")).split(",");
        const csvRows = string.slice(string.indexOf("\n") + 1).split("\n");
    
        const array = csvRows.map((i) => {
          const values = i.split(",");
          const obj = csvHeader.reduce((object, header, index) => {
            object[header] = values[index];
            return object;
          }, {});
          return obj;
        });
    
        setCsvToArray(array);
      };
    
      const handleOnChange = (e) => {
        if (csvFileToArray.length > 0) setCsvToArray([]);
    
        const file = e.target.files[0];
        if (file) {
          fileReader.onload = function (event) {
            const text = event.target.result;
            csvFileToArray(text);
          };
    
          fileReader.readAsText(file);
        }
      };
    
      console.log(csvToArray);
    
      return (
        <>
          <input
            type="file"
            id="csvFileInput"
            accept=".csv"
            onChange={handleOnChange}
          />
          <Map csvToArray={csvToArray} />
        </>
      );
    }
    
    function RenderCsvToArray({ csvToArray }) {
      const map = useMap();
    
      useEffect(() => {
        if (csvToArray.length === 0) return;
    
        const myPoints = csvToArray.map(({ Latitude, Longitude }) => [
          Latitude,
          Longitude
        ]);
        const myBounds = new L.LatLngBounds(myPoints);
        map.fitBounds(myBounds);
      }, [csvToArray]);
    
      return csvToArray?.map(({ Latitude, Longitude, Title }, index) => (
        <Marker key={index} icon={icon} position={[Latitude, Longitude]}>
          <Popup>{Title}</Popup>
        </Marker>
      ));
    }
    

    You can see the full implementation on the demo

    I have also inlcuded two csv files to play with in the form of

    Title,Latitude,Longitude
    Trinity College,41.745167,-72.69263
    Wesleyan University,41.55709,-72.65691
    

    and

    Group,Title,Image,Description,Address,Latitude,Longitude
    a,Trinity College,https://www.edx.org/sites/default/files/trinity1.jpg,"Not in the link <a href=""http://www.trincoll.edu"" target=""_blank"">view website</a> more not in the link","300 Summit St - Hartford CT 06106,41.745167,-72.69263
    a,Wesleyan University,https://upload.wikimedia.org/wikipedia/commons/4/41/You_are_here_-_T-shirt.jpg,"<a href=""http://wesleyan.edu"" target=""_blank"">view website</a>",45 Wyllys Ave Middletown CT 06459,41.55709,-72.65691