Skip to content
Advertisement

My app does not want to re-render, however the list in the context does

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='&copy; <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='&copy; <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='&copy; <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;
9 People found this is helpful
Advertisement