Skip to content

Updated DataTable for alternate key #5907

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 22 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
d6cce4a
Updated DataTable for alternate key
bibektamang7 Apr 8, 2025
b1fa71e
feat(DataTable): allow alternate keyField support
bibektamang7 Apr 10, 2025
78622ec
Merge branch 'main' into feat/DataTable-alternate-key
bibektamang7 Apr 10, 2025
4e27e2b
Merge branch 'main' into feat/DataTable-alternate-key
bibektamang7 Apr 13, 2025
e57bc5c
Merge branch 'main' into feat/DataTable-alternate-key
francinelucca Apr 14, 2025
56a81ba
Merge branch 'primer:main' into feat/DataTable-alternate-key
bibektamang7 Apr 15, 2025
f64d14f
feat(DataTable): add support for custom row ID via getRowId prop
bibektamang7 Apr 15, 2025
dd44889
Merge branch 'main' into feat/DataTable-alternate-key
bibektamang7 Apr 18, 2025
82ac605
fix: format
francinelucca Apr 22, 2025
9018ade
fix: lint
francinelucca Apr 22, 2025
5aabd8f
refactor(DataTable): hoist default getRowId and revert row key to row.id
bibektamang7 Apr 24, 2025
05a18bd
Delete .changeset/bumpy-onions-clap.md
francinelucca Apr 24, 2025
31ceb4d
Merge branch 'main' into feat/DataTable-alternate-key
francinelucca Apr 24, 2025
34171da
Merge branch 'main' into feat/DataTable-alternate-key
francinelucca Apr 24, 2025
456595c
Merge branch 'main' into feat/DataTable-alternate-key
francinelucca Apr 25, 2025
18ad665
Merge branch 'primer:main' into feat/DataTable-alternate-key
bibektamang7 Apr 29, 2025
f1ce83b
test: add useTable tests for getRowId override and fallback behavior
bibektamang7 Apr 29, 2025
b5984d8
Update packages/react/src/DataTable/__tests__/DataTable.test.tsx
bibektamang7 Apr 29, 2025
2dc7f67
Merge branch 'main' into feat/DataTable-alternate-key
francinelucca Apr 30, 2025
d78ee47
Merge branch 'main' into feat/DataTable-alternate-key
francinelucca Apr 30, 2025
b8edd0d
Merge branch 'main' into feat/DataTable-alternate-key
francinelucca Apr 30, 2025
c9eb5bd
Fix: lint/text errors from CI
bibektamang7 May 1, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/shaky-hornets-train.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@primer/react': minor
---

feat(Datatable): add optional getRowId prop to support custom row identifiers
15 changes: 15 additions & 0 deletions packages/react/src/DataTable/DataTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,19 @@ export type DataTableProps<Data extends UniqueRow> = {
* currently sorted column
*/
initialSortDirection?: Exclude<SortDirection, 'NONE'>

/**
* Provide a function to determine the unique identifier for each row.
* This function allows you to customize the key used for the row.
* By default, the table uses the `id` field from the data.
* @param rowData The row data object for which the ID is being retrieved.
* @returns The unique identifier for the row, which can be a string or number.
*/
getRowId?: (rowData: Data) => string | number
}

function defaultGetRowId<D extends UniqueRow>(row: D) {
return row.id
}

function DataTable<Data extends UniqueRow>({
Expand All @@ -60,12 +73,14 @@ function DataTable<Data extends UniqueRow>({
data,
initialSortColumn,
initialSortDirection,
getRowId = defaultGetRowId,
}: DataTableProps<Data>) {
const {headers, rows, actions, gridTemplateColumns} = useTable({
data,
columns,
initialSortColumn,
initialSortDirection,
getRowId,
})

return (
Expand Down
44 changes: 42 additions & 2 deletions packages/react/src/DataTable/__tests__/DataTable.test.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import userEvent from '@testing-library/user-event'
import {render, screen, getByRole, queryByRole, queryAllByRole} from '@testing-library/react'
import {render, screen, getByRole, queryByRole, queryAllByRole, renderHook} from '@testing-library/react'
import React from 'react'
import {DataTable, Table} from '../../DataTable'
import type {Column} from '../column'
import {createColumnHelper} from '../column'
import {getGridTemplateFromColumns} from '../useTable'
import {getGridTemplateFromColumns, useTable} from '../useTable'

describe('DataTable', () => {
it('should render a semantic <table> through `data` and `columns`', () => {
Expand Down Expand Up @@ -1064,4 +1064,44 @@ describe('DataTable', () => {
})
})
})

it('overrides row.id with result of getRowId function', () => {
const data = [
{id: 1, name: 'Sabine', _uid: 'abc123'},
{id: 2, name: 'The Matador', _uid: 'abc12334'},
]

const getRowId = (row: {id: number; name: string; _uid: string}) => row._uid

const {result} = renderHook(() =>
useTable({
data,
columns: [],
getRowId,
}),
)

expect(result.current.rows[0].id).toBe('abc123')
expect(result.current.rows[1].id).toBe('abc12334')
})

it('uses default row.id when getRowId is not provided', () => {
const data = [
{id: 1, name: 'Sabine', _uid: 'abc123'},
{id: 2, name: 'The Matador', _uid: 'abc12334'},
]

const getRowId = (row: {id: number; name: string; _uid: string}) => row.id

const {result} = renderHook(() =>
useTable({
data,
columns: [],
getRowId,
}),
)

expect(result.current.rows[0].id).toBe('1')
expect(result.current.rows[1].id).toBe('2')
})
})
7 changes: 5 additions & 2 deletions packages/react/src/DataTable/useTable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ interface TableConfig<Data extends UniqueRow> {
data: Array<Data>
initialSortColumn?: string | number
initialSortDirection?: Exclude<SortDirection, 'NONE'>
getRowId: (rowData: Data) => string | number
}

interface Table<Data extends UniqueRow> {
Expand Down Expand Up @@ -47,6 +48,7 @@ export function useTable<Data extends UniqueRow>({
data,
initialSortColumn,
initialSortDirection,
getRowId,
}: TableConfig<Data>): Table<Data> {
const [rowOrder, setRowOrder] = useState(data)
const [prevData, setPrevData] = useState(data)
Expand Down Expand Up @@ -181,15 +183,16 @@ export function useTable<Data extends UniqueRow>({
return {
headers,
rows: rowOrder.map(row => {
const rowId = getRowId(row)
return {
id: `${row.id}`,
id: `${rowId}`,
getValue() {
return row
},
getCells() {
return headers.map(header => {
return {
id: `${row.id}:${header.id}`,
id: `${rowId}:${header.id}`,
column: header.column,
rowHeader: header.column.rowHeader ?? false,
getValue() {
Expand Down
Loading