Reputation: 2404
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 as shown below:
In the table shown on the print screen there are 16 vessels, however they are from different companies. The number of logos shown is exactly the 16, like the number of the rows of the table.
The problem is that I see only one logo instead of the logos of all the other companies present on the table (and therefore on the google-map
).
I already prepared an association map as is possible to see in the code below:
ShipTracker.js:
import donjonImage from '../logos/donjon.jpg';
import dutraImage from '../logos/dutra.png';
import glddImage from '../logos/greatlakesdredgeanddock.png';
const shipCompanyMap = {
Michigan: 'DONJON',
STUYVESANT: 'DUTRA',
Ellis_Island: 'GREATLAKESDREDGEANDDOCK'
};
const companyImageMap = {
DONJON: donjonImage,
DUTRA: dutraImage,
GREATLAKESDREDGEANDDOCK: glddImage,
};
const associationMap = Object.values(shipCompanyMap).reduce(
(acc, curr) => ({
...acc,
[curr]: companyImageMap[curr]
}),
{}
);
const Ship = ({ ship }) => {
const shipName = ship.NAME;
const company = shipCompanyMap[shipName];
const shipImage = companyImageMap[company];
return (
<div>
<img src={glddImage} alt="Logo" /> // <-- I think loop should go here?
</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;
On the GoogleMap.js file is where I render the logos and where (I think), I should operate a filtering or a search to make sure that the logos corresponding to the company shown on the map is shown:
import { Ship } from '../components/ShipTracker';
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;
}
// Other operations.....
render() {
return (
<div className="google-map">
<GoogleMapReact
bootstrapURLKeys={{ key: 'My_KEY' }}
center={{
lat: 42.4,
lng: -71.1
}}
zoom={8}
>
{this.state.ships.map((ship) => ( // <-- maybe the filter function here?
<Ship ship={ship} key={ship.CALLSIGN} lat={ship.LATITUDE} lng={ship.LONGITUDE} />
))}
</GoogleMapReact>
</div>
);
}
}
What I have done so far::
1) This is a loop problem. I have tried to loop through the company extracted by the API provided and trying to match that company with its logo and show it on a google-map but I am not sure how to organize the loop as I only see one logo instead of more.
2) After doing some research I came across the filtering function and tried to use a bit to loop through an array of logos.
3) I thought that this post was exactly what I was looking for and tried to apply after studying how to use it. However I was still not able to loop through an array and assign each company to its logo.
Thanks for pointing in the right direction to solve this problem.
Upvotes: 2
Views: 332
Reputation: 30390
If I understand correctly, the issue here is that rendering of the logo image in your <Ship />
component needs to be dynamic. Currently it's static, and is "hard coded" to the glddImage
image, which is why only one logo is shown.
Assuming that the values of ship.NAME
in <Ship />
are any one of "Michigan"
, "STUYVESANT"
, or "Ellis_Island"
, then the following updates should complete your implementation:
const Ship = ({ ship }) => {
const shipName = ship.NAME;
const company = shipCompanyMap[shipName];
/* Optional */
const defaultFallbackImage = "../path/to/image-not-found-placeholder.png"
/* Use fallback image if no company image found */
const shipImage = companyImageMap[company] || defaultFallbackImage;
return (
<div>
{/* Render shipImage image */}
<img src={shipImage} alt="Logo" />
</div>
);
};
export { Ship };
Upvotes: 2
Reputation: 139
It looks like you are setting the src
for each ship in your Ship
definition, where you set it to glddImage
. This is not dynamic, and will yield the same result for each ship. You only attempt to map through your array of ships after this has been done. This could be fixed by mapping through your source for logos within the definition of Ship
.
Upvotes: 0