Skip to content

Commit 90c36df

Browse files
fix(data-table): add 'use no memo' to opt out of React Compiler
The DataTable shared components (data-table.tsx, data-table-filter.tsx) were being compiled by React Compiler, which incorrectly memoized callbacks and state in DataTableFacetedFilter (Set mutation in event handlers) and other table-bound components. This broke search inputs and filter dropdowns on Knowledge Base, Secret Store, AI Agent, and Remote MCP list pages. Adding the 'use no memo' directive opts these files out of React Compiler, matching the pattern already used by the list page files. Also adds integration tests verifying the search input value updates on keystroke and can be cleared and reused. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 9c78239 commit 90c36df

File tree

3 files changed

+102
-0
lines changed

3 files changed

+102
-0
lines changed

frontend/src/components/pages/knowledgebase/list/knowledge-base-list-page.test.tsx

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -429,4 +429,102 @@ describe('KnowledgeBaseList', () => {
429429

430430
expect(screen.getByRole('button', { name: 'Next Page' })).toBeDisabled();
431431
});
432+
433+
test('search input value updates on each keystroke', async () => {
434+
const user = userEvent.setup();
435+
436+
const kb1 = create(KnowledgeBaseSchema, {
437+
id: 'kb-1',
438+
displayName: 'Alpha',
439+
description: '',
440+
tags: {},
441+
});
442+
443+
const transport = createRouterTransport(({ rpc }) => {
444+
rpc(listKnowledgeBases, () =>
445+
create(ListKnowledgeBasesResponseSchema, {
446+
knowledgeBases: [kb1],
447+
nextPageToken: '',
448+
})
449+
);
450+
});
451+
452+
renderWithFileRoutes(<KnowledgeBaseList />, { transport });
453+
454+
await waitFor(() => {
455+
expect(screen.getByText('Alpha')).toBeVisible();
456+
});
457+
458+
const filterInput = screen.getByPlaceholderText('Filter knowledge bases...');
459+
460+
await user.type(filterInput, 'test');
461+
462+
// The input value must reflect what was typed — a React Compiler
463+
// memoization bug would freeze it at the initial empty string.
464+
expect(filterInput).toHaveValue('test');
465+
});
466+
467+
test('search input can be cleared and reused', async () => {
468+
const user = userEvent.setup();
469+
470+
const kb1 = create(KnowledgeBaseSchema, {
471+
id: 'kb-1',
472+
displayName: 'Alpha KB',
473+
description: '',
474+
tags: {},
475+
});
476+
477+
const kb2 = create(KnowledgeBaseSchema, {
478+
id: 'kb-2',
479+
displayName: 'Beta KB',
480+
description: '',
481+
tags: {},
482+
});
483+
484+
const transport = createRouterTransport(({ rpc }) => {
485+
rpc(listKnowledgeBases, () =>
486+
create(ListKnowledgeBasesResponseSchema, {
487+
knowledgeBases: [kb1, kb2],
488+
nextPageToken: '',
489+
})
490+
);
491+
});
492+
493+
renderWithFileRoutes(<KnowledgeBaseList />, { transport });
494+
495+
await waitFor(() => {
496+
expect(screen.getByText('Alpha KB')).toBeVisible();
497+
expect(screen.getByText('Beta KB')).toBeVisible();
498+
});
499+
500+
const filterInput = screen.getByPlaceholderText('Filter knowledge bases...');
501+
502+
// Type to filter down to Alpha only
503+
await user.type(filterInput, 'Alpha');
504+
505+
await waitFor(() => {
506+
expect(screen.getByText('Alpha KB')).toBeVisible();
507+
expect(screen.queryByText('Beta KB')).not.toBeInTheDocument();
508+
});
509+
510+
// Clear the input completely
511+
await user.clear(filterInput);
512+
expect(filterInput).toHaveValue('');
513+
514+
// Both rows should reappear
515+
await waitFor(() => {
516+
expect(screen.getByText('Alpha KB')).toBeVisible();
517+
expect(screen.getByText('Beta KB')).toBeVisible();
518+
});
519+
520+
// Type again to filter down to Beta
521+
await user.type(filterInput, 'Beta');
522+
523+
await waitFor(() => {
524+
expect(screen.queryByText('Alpha KB')).not.toBeInTheDocument();
525+
expect(screen.getByText('Beta KB')).toBeVisible();
526+
});
527+
528+
expect(filterInput).toHaveValue('Beta');
529+
});
432530
});

frontend/src/components/redpanda-ui/components/data-table-filter.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
'use no memo';
2+
13
import type { Table } from '@tanstack/react-table';
24
import { Ellipsis, FilterIcon, X } from 'lucide-react';
35
import React, { isValidElement, memo, useCallback, useEffect, useMemo, useState } from 'react';

frontend/src/components/redpanda-ui/components/data-table.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
'use no memo';
2+
13
'use client';
24

35
import type { Column, ColumnDef, Row, Table } from '@tanstack/react-table';

0 commit comments

Comments
 (0)