Ant Design Table vs. Data Items: Ensuring Unique rowKey Without Public Exposure?
0 reputation · 16 Dec 2020, 15:47 UTC
0 reputation · 16 Dec 2020, 15:47 UTC
In Ant Design Table, the rowKey prop is mandatory for stable rendering. The default key is the string 'key', so data objects without a key property cause React to reuse the same key for every row.
This silent failure generates duplicate key warnings, unstable row ordering, and can expose sensitive identifiers if the key is derived from a private field. The documentation states that rowKey is required but offers no guidance for non‑unique or absent values, leaving developers to choose ad‑hoc solutions such as the array index.
Using the index breaks selection, sorting, and editing when the dataset changes, yet it is the most common workaround. The lack of a clear fallback or error handling creates an unresolved decision point for developers who need to avoid accidental public exposure.
What strategies can be employed to guarantee unique rowKey values without leaking sensitive data? How should Ant Design evolve its Table component to provide a safe default or validation mechanism when rowKey is missing or non‑unique? Are there recommended patterns for generating deterministic keys that remain stable across reorders yet remain internal?
To guarantee a stable rowKey without exposing sensitive data, generate a deterministic identifier that is derived only from non‑sensitive fields or maintain an internal map of stable IDs.
<Table rowKey={(record) => record.id} />
import { createHash } from 'crypto';
function makeKey(record) {
const source = JSON.stringify({ name: record.name, createdAt: record.createdAt });
return createHash('sha256').update(source).digest('hex').slice(0, 8);
}
<Table rowKey={makeKey} />
Map (or a WeakMap if you prefer automatic cleanup). Return that ID via rowKey. This keeps the key completely internal and stable across reorders, additions, or removals as long as the map persists:
const internalIdMap = new Map();
let nextId = 1;
function getInternalId(record) {
if (!internalIdMap.has(record)) {
internalIdMap.set(record, nextId++);
}
return internalIdMap.get(record);
}
<Table rowKey={getInternalId} />
rowKey is missing or when duplicate keys are detected.keyGenerator prop that defaults to a safe internal‑map strategy, removing the need for developers to implement their own fallback.stableHash(record, fields)) in the docs to help teams create deterministic, non‑exposed keys.Use comments to ask for clarification. Post a solution as an answer.
33,275 reputation · 16 Dec 2020, 21:09 UTC
When your data lacks a public unique field, a lightweight pattern is to keep a WeakMap that assigns a stable ID to each record object. This keeps the key internal, prevents leaks, and survives re‑renders as long as the component instance lives.
const idMap = new WeakMap();
let nextId = 1;
const keyFn = record => {
if (!idMap.has(record)) {
idMap.set(record, `row-${nextId++}`);
}
return idMap.get(record);
};
<Table rowKey={keyFn} dataSource={data} />
Because the key is derived from the object reference, it remains stable across sorting, filtering, or pagination, yet it never exposes a raw identifier in the DOM. For extra safety, Ant Design could add a runtime check that logs or throws when duplicate keys surface, helping developers catch accidental duplicates early.