Short story: I am making my own GIS (geographic information system) and want to be able to upload JSON files with geographical data. I do not however want to save files in a database, just in a list. Furthermore I’m using Context to send data to the (leaflet) component. When I upload new JSONs to the layerList it gets updated but the component does not re-render. I have console logged the list after uploading files and the all get added.
The use of context is based off of DevEd’s guide on context from youtube https://www.youtube.com/watch?v=35lXWvCuM8o&t=1352s
Here is my code
Context:
import React, {createContext, useState, useEffect} from 'react';
import "../../App.css";
export const FileContext = createContext()
export const FileProvider = (props) => {
const [layerList, setLayerList] = useState('');
return(
<FileContext.Provider value = {[layerList, setLayerList]}>
{props.children}
</FileContext.Provider>
);
}
Upload component:
import React, {createContext, useContext, useState} from 'react';
import "../../App.css";
import {FileContext} from './FileContext'
function FileUpload() {
const [layerList, setLayerList] = useContext(FileContext)
const onFileChange = e => {
const fileReader = new FileReader();
fileReader.readAsText(e.target.files[0], "UTF-8");
fileReader.onload = e => {
setLayerList(prevLayer => [prevLayer, JSON.parse(e.target.result)]);
};
}
return (
<div>
<div id='fileupload'>
<input type="file" onChange={onFileChange} />
</div>
</div>
);
}
export default FileUpload;
Map:
import React, { useContext } from 'react';
import { Map, TileLayer, GeoJSON} from 'react-leaflet'
import "../App.css";
import { FileContext } from '../LandingPage/ToolbarComponents/FileContext';
import data from '../Layers/layer1.json'
import data1 from '../Layers/layer2.json'
function MapOslo() {
const [layerList] = useContext(FileContext)
return (
<Map center={[59.93, 10.75]} zoom={1}>
<TileLayer
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
attribution='© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
/>
<GeoJSON data={layerList} style={['color','#006400']} />
</Map>
);
}
export default MapOslo;
Advertisement
Answer
EDIT: I pulled your repo and I think it’s solved now. Notice how the map.js component it’s logging the data from the updated .json file. Your map.js component should look like the following:
import React, { useContext, useEffect, useState} from 'react';
import { Map, TileLayer, GeoJSON} from 'react-leaflet'
import "../App.css";
import { FileContext } from ../LandingPage/ToolbarComponents/FileContext';
import data from '../Layers/layer1.json'
import data1 from '../Layers/layer2.json'
function MapOslo() {
const [layerList] = useContext(FileContext);
const [layerState, setLayerState] = useState(layerList);
useEffect(() => {
setLayerState(layerList);
console.log(layerState);
});
return (
<Map center={[59.93, 10.75]} zoom={1}>
<TileLayer
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
attribution='© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
/>
<GeoJSON data={layerState} style={['color','#006400']} />
</Map>
);
}
export default MapOslo;
EDIT 2: I’m not sure what do you mean by the layers… but it’s showing the marker now with the static position you previously included in there. See below updated map.js:
import React, { useContext, useEffect, useState} from 'react';
import { Map, TileLayer, GeoJSON, Marker, Popup} from 'react-leaflet'
import "../App.css";
import { FileContext } from '../LandingPage/ToolbarComponents/FileContext';
import data from '../Layers/layer1.json'
import data1 from '../Layers/layer2.json'
function MapOslo() {
const [layerList] = useContext(FileContext);
const [layerState, setLayerState] = useState(layerList);
useEffect(() => {
setLayerState(layerList);
console.log(layerState);
});
const position = [59.93, 10.75];
return (
<Map center={position} zoom={6}>
<TileLayer
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
attribution='© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
/>
<GeoJSON data={layerState} style={['color','#006400']} />
<Marker position={position}>
<Popup>A pretty CSS3 popup.<br />Easily customizable.</Popup>
</Marker>
</Map>
);
}
export default MapOslo;