I have an array that gets added to, removed from, and updated through websockets. I am displaying the array data in a table.
The data is being displayed, but it only works correctly when there is one object in the array. If the array is added to through a websocket event, instead of displaying both objects of the array, the object is simply replaced by the new addition to the array.
So, the table is only showing the most recent object added to the array - even though there are multiple objects in the array.
Code for displaying the array:
interface TableEntry {
address: string;
amount: string;
children?: React.ReactNode;
}
...
<TableContainer>
<Table variant="simple">
<Thead>
<Tr>
<Th fontFamily={"Orbitron"}>User</Th>
<Th fontFamily={"Orbitron"}>Amount</Th>
</Tr>
</Thead>
<Tbody>
{ entryArray?.map((entry) => {
return entry.address == globalAddress ? (
<Tr key={entry.address} bg={"rgba(255, 255, 255, 0.05)"}>
<Td fontFamily={"Orbitron"}>{shorten(entry.address)}</Td>
<Td fontFamily={"Orbitron"}>{entry.amount}</Td>
</Tr>
) : (
<Tr key={entry.address}>
<Td fontFamily={"Orbitron"}>{shorten(entry.address)}</Td>
<Td fontFamily={"Orbitron"}>{entry.amount}</Td>
</Tr>
)
})}
</Tbody>
</Table>
</TableContainer>
Edit: Code for updating/creating the array:
//Add new entry
useEffect(() => {
var tempEntries = entryArray;
socket.on("userAdd", (data) => {
tempEntries.push({ address: data[0], amount: data[1] });
setEntryArray(tempEntries);
tempEntries = [];
});
return function () {
socket.off("userAdd");
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
useEffect(() => {
socket.on("userUpdate", (data) => {
var tempEntries = entryArray.map(
(element: TableEntry) =>
element.address == data[0]
? { ...element, address: "updated" } //update the found element
: element //keep the original element
);
setEntryArray(tempEntries);
tempEntries = [];
});
return function () {
socket.off("userUpdate");
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
How can I change my code to iterate through the array and display every Object of the array?
CodePudding user response:
useEffect(() => {
var tempEntries = entryArray;
socket.on("userAdd", (data) => {
tempEntries.push({ address: data[0], amount: data[1] });
setEntryArray(tempEntries);
tempEntries = [];
});
return function () {
socket.off("userAdd");
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
This effect only runs once, on the initial mount. At that time, entryArray
is an empty array. So every time userAdd
happens, you start from an empty array and add one element.
Instead, use the function version of set state to get the latest state, and build your new array from that. Make sure you're creating a new array, not pushing into the existing array.
useEffect(() => {
socket.on("userAdd", (data) => {
setEntryArray(prev => {
return [...prev, { address: data[0], amount: data[1] }]
});
});
return function () {
socket.off("userAdd");
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
You'll need to make a similar change in your update effect:
useEffect(() => {
socket.on("userUpdate", (data) => {
setEntryArray((prev) => {
return prev.map(
(element: TableEntry) =>
element.address == data[0]
? { ...element, address: "updated" } //update the found element
: element //keep the original element
);
});
});
return function () {
socket.off("userUpdate");
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);