I just want to transfer the data from one component to a table component. So after selecting the option from the dropdown menu, it should reflect all the details of that selected option inside the table. I have made two components:
Devdropdown.jsx:
import React, { useState, useEffect, useMemo } from "react";
import Tables from "./Tables";
const Devdropdown = () => {
const [devices, setDevices] = useState([{}]);
const [selected, setSelected] = useState();
const url = "http://localhost:3000/devices";
useEffect(() => {
async function getDevices() {
const response = await fetch(url);
const body = await response.json();
setDevices(body.data);
}
getDevices();
}, []);
const handleChange = (e) => {
e.preventDefault();
setSelected(e.target.value);
};
const uniqueDeviceIds = useMemo(
() => Array.from(new Set(devices.map((device) => device.device_id))),
[devices]
);
console.log(devices);
return (
<div>
<h1>Aircraft {selected}</h1>
<select
value={selected}
onChange={handleChange}
placeholder="select an option"
>
{devices
? uniqueDeviceIds.map((deviceId) => (
<option key={deviceId}>{deviceId}</option>
))
: null}
</select>
<Tables data={devices[selected]} />
</div>
);
};
export default Devdropdown;
Tables.jsx:
import React from "react";
const Tables = (props) => {
return (
<div>
<table>
<tr>
<th>Timestamp</th>
<th>Location</th>
</tr>
<tr>
<td>{props.data}</td>
<td>{props.data}</td>
</tr>
</table>
</div>
);
};
export default Tables;
I just want to reflect the timsetamp and location features of the selected element , inside the table. Below is the screenshot of the devices object where I want timestamp and location attributes inside the table component.
Thanks and regards
You can create a Map
to group by your device_id
, this will allow you to populate your dropdown with unique options by getting the keys of the map (rather than using a Set
), and also allow you to associate the selected option with an array of devices
that all have the same device_id
:
const deviceMap = useMemo(() => {
const grouped = new Map();
for (const device of devices) {
const currDeviceArr = grouped.get(device.device_id) ?? [];
currDeviceArr.push(device); // add the current device to the associated device_id array
grouped.set(device.device_id, currDeviceArr);
}
return grouped;
}
[devices]
);
return (
<div>
<h1>Aircraft {selected}</h1>
<select
value={selected}
onChange={handleChange}
placeholder="select an option"
>
{devices
? Array.from(deviceMap.keys(), (device_id) => (
<option key={device_id}>{device_id}</option>
))
: null}
</select>
<Tables data={deviceMap.get(selected)} />
</div>
);
Then you can update your Table
component to map over the devices with the selected device_id:
const Tables = ({ data = []}) => {
return (
<div>
<table>
<tr>
<th>Timestamp</th>
<th>Location</th>
</tr>
{
data.map((device, i) => <tr key={i}>
<td>{device.timestamp}</td>
<td>{device.location}</td>
</tr>)
}
</table>
</div>
);
};
Another approach would be to stick the Devdropdown
component that you have now, and then filter the devices
array out based on the selected option, but this isn't as efficient as you now looping over devices
multiple times:
<Tables data={devices.filter(device => device.device_id === selected)} />
You could also put the above .filter()
computation in a useMemo()
hook so that it only recomputes the array when devices
or selected
changes, and not on every rerender. Once you have done this, you can apply the same change to your Tables
component as shown above.