Search code examples
javascriptreactjsleafletreact-leaflet

React leaflet flyto function on table


Onclick tmp() on the table fetches location of point. I have tried UseMapEvents and UseRef method but get an error that map is called before initialization. Just want the map to fly to marker when user click on the table row Webpage. Here is the full code.

function App() {
  var [loc, setloc] = useState();
  var [getlat] = useState();
  var [getlong] = useState();
  const [search, setSearch] = useState('')
  var [setttmp] = useState();
  const [geojsonData] = useState(import_Data);
  
// get lat long value 
  var tmp = (index) => () => {

    // to get lat long deatils from the table
    var tmplat = Object.values(setttmp[index].props.children[3].props);
    var tmplong = Object.values(setttmp[index].props.children[4].props);
    getlat = Object.values(tmplat)[1];
    getlong = Object.values(tmplong)[1];
    // loc = "["+getlat+","+getlong+"]";
    loc = "{lat: " + getlat + ", lng: " + getlong + "}";
    console.log(loc)
   }
 
  return (<>

    <div className='right_container'>
      <div className='home'>Home
      </div>
      <div className='container_table'>
        <div onChange={(e) => setSearch(e.target.value)} style={{ textAlign: 'center', }}>
          <input type="text" name="search" placeholder='Search .....' />
        </div>
        <div style={{ textAlign: 'center', padding: '1%' }}>{"count : WIP"}
        </div>
        <br></br>

        <Table style={{ width: '100%', cursor: 'pointer' }} id='table'>
          <thead>
            <tr style={{ position: 'sticky', top: '0px' }}>
              <th style={{ width: '45%' }}>Title</th>
              <th style={{ width: '30%' }}>Type</th>
              <th style={{ width: '25%' }}>Company</th>
            </tr>
          </thead>
          <tbody>
            {setttmp =
              geojsonData.features.filter((feature) => { return search.toLowerCase() === '' ? feature : feature.properties.title.toLowerCase().includes(search) || feature.properties.company.toLowerCase().includes(search); })
                .map((feature, index) => {
                  // trying to save lat long
                  return (
                    <tr key={index} id='table_row' onClick={tmp(index)}>
                      <td>{feature.properties.title}</td>
                      <td>{feature.properties.job_type}</td>
                      <td>{feature.properties.company}</td>
                      <td style={{ display: 'none' }}>{feature.properties.lat}</td>
                      <td style={{ display: 'none' }}>{feature.properties.long}</td>
                    </tr>
                  )
                }
                )
            }
          </tbody>
        </Table>
      </div>
      <div style={{ fontSize: '30px', padding: '20px 20px', textAlign: 'center' }}>About
      </div>
    </div>

    <div className='left_container'>
      <MapContainer center={[43.0059455,-123.8925908]} zoom={6} style={{ height: "100vh", width: "100%" }}>
        <LayersControl position='bottomleft'>
          <BaseLayer name='OpenStreetMap'>
            <TileLayer url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png" attribution='&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors' />
          </BaseLayer>
          <BaseLayer name="NASA Gibs Blue Marble">
            <TileLayer url="https://gibs-{s}.earthdata.nasa.gov/wmts/epsg3857/best/BlueMarble_ShadedRelief_Bathymetry/default//EPSG3857_500m/{z}/{y}/{x}.jpeg" attribution="&copy; NASA Blue Marble, image service by OpenGeo" maxNativeZoom={8} />
          </BaseLayer>
          <BaseLayer checked name="OSM-Dark">
            <TileLayer url="https://{s}.tile.openstreetmap.fr/hot/{z}/{x}/{y}.png" attribution='&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors' className='map-tiles' />
          </BaseLayer>
        </LayersControl>

        {jobdata.features.map((jlist, index) => (
          <Marker key={index} position={[jlist.properties.lat, jlist.properties.long]}>
            <Popup position={[jlist.properties.lat, jlist.properties.long]}>
              <div style={popupHead}>{jlist.properties.title}</div>
              <div>
                {/* <h2>{jlist.properties.title}</h2> */}
                <p>{"Type : " + jlist.properties.job_type}</p>
                <p>{"Company : " + jlist.properties.company}</p>
                <p>{"Posted : " + jlist.properties.date_posted}</p>
                <p>Apply <a href={jlist.properties.apply_link}>here</a></p>
              </div>
            </Popup>
          </Marker>
        ))}
      </MapContainer>
    </div>
  </>)
};

export default App;

I have tried UseRef and UseMapEvents, havent really tried setViewMap but that would probabaly ends up with same error. Also is there any way to call flyto function within tmp() function as calling two function with onclick on the table row breaks tmp() which fetches lat,long value which is critical to flymap().


Solution

  • First we add onclick event to the table again, this time to render flyto function.

       <tr key={index} id='table_row' onClick={tmp(index)}>
                      <td>{feature.properties.title}</td>
                      <td>{feature.properties.job_type}</td>
    

    as tr already has onclick event, we can either pass one more, or create a new on title.

         <td onClick={fly}>{feature.properties.title}</td>
    

    now to the main App function

         const mapRef = useRef(null);
       const fly = ()=>{
      // console.log(loc)
     mapRef.current.flyTo(loc,14);
     }
    

    So the first onclick on table get use latlng values stored in loc. 2nd onclick on title column will than activate flyto function. Note we need to add "ref={mapRef}" to the Mapcontainer tag.