I implemented a realtime data grid table using React Redux and SignalR. After the first item is added to table/the first dispatch happens, the following console error is logged:
Warning: Each child in a list should have a unique "key" prop.
Check the render method ofBody
. See https://reactjs.org/link/warning-keys for more information.
I understand what the issue is but how do I fix it?
import { useEffect } from "react";
import { useDispatch, useSelector } from "react-redux";
import { Table } from "antd";
import { HubConnectionState } from "redux-signalr";
import hubConnection from "../store/middlewares/signalr/signalrSlice";
import { Stock, addStock } from "../store/reducers/stockSlice";
import { RootState } from "../store";
const DataGrid = () => {
const dispatch = useDispatch();
const stocks = useSelector((state: RootState) => state.stock.stocks);
useEffect(() => {
if (hubConnection.state !== HubConnectionState.Connected) {
hubConnection
.start()
.then(() => {
console.log("Started connection via SignalR");
hubConnection.stream("GetStockTickerStream").subscribe({
next: async (item: Stock) => {
console.log(item);
dispatch(addStock(item)); // Dispatch addStock action to update Redux store
},
complete: () => {
console.log("Completed");
},
error: (err) => {
console.error(err);
},
});
})
.catch((err) => console.error(`Faulted: ${err.toString()}`));
}
}, [dispatch]);
return (
<Table dataSource={stocks}>
<Table.Column title="Symbol" dataIndex="symbol" key="symbol" />
<Table.Column title="Price" dataIndex="price" key="price" />
</Table>
);
};
export default DataGrid;
import { createSlice, PayloadAction } from "@reduxjs/toolkit";
export type Stock = Readonly<{
id: number;
symbol: string;
price: number;
}>;
export type StockState = Readonly<{
stocks: Stock[];
}>;
const initialState: StockState = {
stocks: [],
};
const stockSlice = createSlice({
name: "stock",
initialState: initialState,
reducers: {
addStock: (state, action: PayloadAction<Stock>) => {
state.stocks = [action.payload];
},
},
});
export const { addStock } = stockSlice.actions;
export default stockSlice.reducer;
4
Answers
I guess the problem is not the key of your columns, but the key of your rows. Can you show the structure of your datasource?
In the antd documentation, the dataSource is supposed to look like this:
Make sure that each row has its own key.
Regarding your edit:
Try to format your row data, so that it looks like this:
Key property is expected in the data
or you can pass a
rowKey
prop of typefunction(record): string
as given in the apiAdd or edit a row
beta docs about updating array in React
Hope it helps
As suggested by Azzy and ActionReacto you are missing the key prop, but the problem is how to add it using selector?, so here is the way you can do it
here instead of index ,you can use any other unique value as key like stock.id.
Hope this will help.
The problem is you’re passing key as a prop to a React component class and the
key
prop is reserved for loop-generated (e.g.map()
) components. React is telling you that every component needs to have a unique key. This has nothing to do with the key prop in your column definition for antd. So instead of passing the key as a prop, try this: