Emanuele
Emanuele

Reputation: 2404

ReactJS - JavaScript - HTML: How to update a dropdown menu after selection

The problem: How do I updated a dropdown menu after selection?

Sorry if this question is simple but I have been trying many different ways to make it work. I am building a boat visualizer using AISHub APIs. After inquiring the APIs I am able to obtain a json file with the vessels I am interested in and inject these vessels inside a table and show their marker on a google-map. Now some vessel do some functions, others do something else, and I am trying to filter that using a dropdown menu.

Below the most important part of the code:

GoogleMap.js:

class BoatMap extends Component {
    constructor(props) {
        super(props);
        this.state = {
            buttonEnabled: true,
            buttonClickedAt: null,
            progress: 0,
            ships: []
        };
        this.updateRequest = this.updateRequest.bind(this);
        this.countDownInterval = null;
    }

    componentDidMount() {
        this.countDownInterval = setInterval(() => {
            if (!this.state.buttonClickedAt) return;
            const date = new Date();
            const diff = Math.floor((date.getTime() - this.state.buttonClickedAt.getTime()) / 1000);

            if (diff < 90) {
                this.setState({
                    progress: diff,
                    buttonEnabled: false
                });
            } else {
                this.setState({
                    progress: 0,
                    buttonClickedAt: null,
                    buttonEnabled: true
                });
            }
        }, 500);
    }

    componentWillUnmount() {
        clearInterval(this.countdownInterval);
    }

    async updateRequest() {
        const url = 'http://localhost:3001/hello';
        console.log(url);
        const fetchingData = await fetch(url);
        const ships = await fetchingData.json();

        console.log(ships);

        this.setState({
            buttonEnabled: false,
            buttonClickedAt: new Date(),
            progress: 0,
            ships
        });
        setTimeout(() => {
            this.setState({ buttonEnabled: true });
        });
    }

    render() {
        return (
            <div className="google-map">
                <GoogleMapReact
                    bootstrapURLKeys={{ key: 'My_KEY' }}
                    center={{
                        lat: 42.4,
                        lng: -71.1
                    }}
                    zoom={8}
                >
// This will render the customized marker on Google-Map
                    {this.state.ships.map((ship) => (
                        <Ship ship={ship} key={ship.CALLSIGN} lat={ship.LATITUDE} lng={ship.LONGITUDE} />
                    ))}
// This is the dropdown I am trying to update
                    <select className="combo-companies">
                        <option value="All">All</option>
                        <option value="research">research</option>
                        <option value="exploration">exploration</option>
                        <option value="navigation">navigation</option>
                        <option value="drilling">drilling</option>
                    </select>
                </GoogleMapReact>
            </div>
        );
    }
}

ShipTracker.js

const Ship = ({ ship }) => {
    const shipName = ship.NAME;
    const company = shipCompanyMap[shipName];

    const shipImage = companyImageMap[company];
    return (
        <div>
            {/* Render shipImage image */}
            <img src={shipImage} alt="Logo" />
        </div>
    );
};
export { Ship };

const ShipTracker = ({ ships }) => {
    const handleRowClick = (rowValue) => {
        console.log(rowValue);
    };
    return (
        <div className="ship-tracker">
            <Table className="flags-table" responsive hover>
                <thead>
                    <tr>
                        <th>#</th>
                        <th>Name</th>
                        <th>Callsign</th>
                        <th>Heading</th>
                        <th>SOG</th>
                        <th>IMO</th>
                        <th>MMSI</th>
                        <th>Longitude</th>
                        <th>Latitudee</th>
                    </tr>
                </thead>
                <tbody>
                    {ships.map((ship, index) => {
                        const { IMO, NAME, CALLSIGN, HEADING, SOG, MMSI, LONGITUDE, LATITUDE } = ship;
                        const cells = [ NAME, CALLSIGN, HEADING, SOG, IMO, MMSI, LONGITUDE, LATITUDE ];
                        return (
                            <tr onClick={() => handleRowClick(ship)} key={index}>
                                <th scope="row">{index}</th>
                                {cells.map((cell) => <td>{cell}</td>)}
                            </tr>
                        );
                    })}
                </tbody>
            </Table>
        </div>
    );
};

export default ShipTracker;

What I have done so far:

1) After investigating I came across this source which was useful to understand the concept behind the choice. That question remained unanswered and was wondering if the functions componentWillMount and componentWillReceiveProps will have to be implemented or if there is an additional way.

2) This post was useful too, but made me a bit confused as it seems that there need to be setState as an additional function for the implementation.

3) It seems from here that a response has to be provided within a handler function. Although useful I think this post is sum of point 1) + 2).

I know this is a simple example but I was trying to understand the basic concept on how to update a simple dropdown before passing to something more intermediate or advanced. Thanks for pointing in the right direction for solving this problem.

Upvotes: 1

Views: 195

Answers (2)

Guicara
Guicara

Reputation: 1698

filter(ship => ship.type === this.state.type)

I have used ship.type as an example. Do you have a type property on your Ship entity?

Edit:

render() {
    // All the ships
    const ships = this.state.ships;

    // Debug
    console.log('this.state.type: ' + this.state.type);

    // Only the ships matching the dropdown selected value
    const filteredShips = ships.filter(ship => {
        console.log('ship.shipImage: ' + ship.shipImage);

        if (ship.shipImage !== this.state.type) {
            console.log('ship.shipImage does not match the filtered value');
        }

        return ship.shipImage === this.state.type;
    });

    // Debug
    console.log(ships);
    console.log(filteredShips);

    return (
        <div className="google-map">
            <GoogleMapReact
                bootstrapURLKeys={{key: 'My_KEY'}}
                center={{
                    lat: 42.4,
                    lng: -71.1
                }}
                zoom={8}
            >
                {filteredShips.map((ship) => (
                    <Ship ship={ship} key={ship.CALLSIGN} lat={ship.LATITUDE} lng={ship.LONGITUDE}/>
                ))}

                <select className="combo-companies" value={this.state.type} onChange={this.handleChange}>
                    <option value="All">All</option>
                    <option value="research">research</option>
                    <option value="exploration">exploration</option>
                    <option value="navigation">navigation</option>
                    <option value="drilling">drilling</option>
                </select>
            </GoogleMapReact>
        </div>
    );
}

Upvotes: 1

Guicara
Guicara

Reputation: 1698

Ok, so you want to filter the displayed makers on the map regarding the option selected by the user on the dropdown.

You can change the name of type with what you want. The type if one of the dropdown values (all, research, exploration, navigation or drilling).

I have not tested the following code, but it should works!

class BoatMap extends Component {
    constructor(props) {
        super(props);
        this.state = {
            buttonEnabled: true,
            buttonClickedAt: null,
            progress: 0,
            ships: [],
            type: 'All'
        };
        this.updateRequest = this.updateRequest.bind(this);
        this.countDownInterval = null;
    }

    componentDidUpdate(prevProps, prevState) {
        if (this.state.type !== prevState.type) {
            // The user has selected a different value from the dropdown
            // To get this value: this.state.type
            // do anything you want here...
            console.log('dropdown value changed for ' + this.state.type);
        }
    }

    handleChange = e => {
        this.setState({
            type: e.target.value
        });
    };

    render() {
        return (
            <div className="google-map">
                <GoogleMapReact
                    bootstrapURLKeys={{key: 'My_KEY'}}
                    center={{
                        lat: 42.4,
                        lng: -71.1
                    }}
                    zoom={8}
                >
                    {this.state.ships.filter(ship => ship.type === this.state.type).map((ship) => (
                        <Ship ship={ship} key={ship.CALLSIGN} lat={ship.LATITUDE} lng={ship.LONGITUDE}/>
                    ))}

                    <select className="combo-companies" value={this.state.type} onChange={this.handleChange}>
                        <option value="All">All</option>
                        <option value="research">research</option>
                        <option value="exploration">exploration</option>
                        <option value="navigation">navigation</option>
                        <option value="drilling">drilling</option>
                    </select>
                </GoogleMapReact>
            </div>
        );
    }
}

Upvotes: 1

Related Questions