0

I am trying to change the position of the map (change marker). I have (although discouraged to directly manipulate the DOM), attached an event listener to a table and i am getting the right lat & long on <tr> click. I just need some help changing the location of the map. Not sure why it's not working... thanks!

class QuakeMap extends Component {

constructor(props) {
    super(props);

    this.change_location = this.change_location.bind(this);

    this.state = {
        lat: 51.505,
        long: -0.09,
        zoom: 3,
    }
}

componentDidMount() {       

    setTimeout(function() {
        // STORE STATE
        let store_state = store.getState(); 

        // FIRST ELEMENT OF ARRAY TO INITIALIZE MAP
        const quake_arr = store_state.quake_data[0]; 

        // LAT, LONG
        let quake_long = quake_arr[0].geometry.coordinates[0];
        let quake_lat  = quake_arr[0].geometry.coordinates[1];

        // MOST RECENT EARTHQUAKE
        this.setState({ lat: quake_lat, long: quake_long });

        // ON CHANGE, SET POSITION TO UPDATED POSITION      
        this.change_location();
    }.bind(this), 100);


}

change_location() {     

    var position = [this.state.lat, this.state.long];

    let table_bod = document.getElementsByClassName('quake-feed-table-body__table-row-dynamic');

    // GET & PARSE DYNMAIC LAT, LONG FOR EACH CLICK
    let curr_lat = parseFloat(this.props.coord_lat);
    let curr_lng = parseFloat(this.props.coord_lng);

    // UPDATED DYNAMIC POSITION
    let updated_position = [curr_lat, curr_lng];

    for (var i = 0; i < table_bod.length; i++) {
        table_bod[i].addEventListener('click', function() {             
            position[0] = parseFloat(this.children[0].attributes[1].value);
            position[1] = parseFloat(this.children[0].attributes[2].value);

            let current_lat = position[0];
            let current_lng = position[1];

            // ARRAY WITH CURRENT POSITION OF CLICK
            let current_pos = [current_lat, current_lng];
            console.log(current_pos);

            return (
                <div className='section-quake-map p-2'>
                    <Map center={current_pos} zoom={3}>
                        <TileLayer
                          attribution='&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
                          url='http://{s}.tile.osm.org/{z}/{x}/{y}.png'                         
                        />
                        <Marker position={current_pos} />
                     </Map>
                </div>
            )
        })
    }
    console.log(this);

}

render() {
    let position = [this.state.lat, this.state.long];   
    return (
        <div className='section-quake-map p-2'>
            <Map center={position} zoom={this.state.zoom}>
                <TileLayer
                  attribution='&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
                  url='http://{s}.tile.osm.org/{z}/{x}/{y}.png'                         
                />
                <Marker position={position} />
             </Map>
</div>
)

2 Answers 2

1

This solved it:

change_location() {     

    var position = [this.state.lat, this.state.long];

    let table_bod = document.getElementsByClassName('quake-feed-table-body__table-row-dynamic');

    // GET & PARSE DYNMAIC LAT, LONG FOR EACH CLICK
    let curr_lat = parseFloat(this.props.coord_lat);
    let curr_lng = parseFloat(this.props.coord_lng);

    // UPDATED DYNAMIC POSITION
    let updated_position = [curr_lat, curr_lng];

    // SET STATE OF COMPONENT TO NEW LAT LONG WHEN TABLE IS CLICKED
    const set_parent_st = () => {
        this.setState({lat: position[0], long: position[1]});
    };

    // ATTACH AN EVENT LISTENER TO THE FEED TABLE ROWS & STORE LAT, LONG
    for (var i = 0; i < table_bod.length; i++) {
        table_bod[i].addEventListener('click', function() { 

            position[0] = parseFloat(this.children[0].attributes[1].value);
            position[1] = parseFloat(this.children[0].attributes[2].value);

            set_parent_st();                                

        })
    }
}
0

You should call this.setState({lat: current_lat, long: current_long}) inside click handler. To make sure you will have correct this reference, you should use arrow function inside handler instead of function() {} syntax.

So it would be something like:

table_bod[i].addEventListener('click', () => {             
    position[0] = parseFloat(this.children[0].attributes[1].value);
    position[1] = parseFloat(this.children[0].attributes[2].value);

    let current_lat = position[0];
    let current_lng = position[1];

    this.setState({lat: current_lat, long: current_long})
    // You don't have to return anything from this function.
})
1
  • It works now. I ended up using a callback arrow function instead. I couldn't make the event listener's anon function an arrow function because this was pointing to the row being clicked on and that was intentional. I just needed the parent scope to set state and i was able to do that by creating a callback right above the for loop and invoking it inside the event handler. Thanks!
    – Parth J
    Commented Feb 17, 2019 at 21:21

Not the answer you're looking for? Browse other questions tagged or ask your own question.