React
The <FreeGrid> component with props, events and a ref to the API.
Code for this demo
import type { GridApi } from '@freegridjs/core';
import { FreeGrid } from '@freegridjs/react';
import { useMemo, useRef, useState } from 'react';
import { demoColumns, makeRows, type Lang } from './data';
export default function ReactDemo({ lang }: { lang: Lang }) {
const t = (en: string, ko: string) => (lang === 'ko' ? ko : en);
const columns = useMemo(() => demoColumns(lang), [lang]);
const [rows, setRows] = useState(() => makeRows(1000));
const [theme, setTheme] = useState<'light' | 'dark'>('light');
const [clicked, setClicked] = useState('');
const [selected, setSelected] = useState(0);
const grid = useRef<GridApi | null>(null);
// Keep option objects stable; a new object on every render would re-apply them.
const summary = useMemo(() => ({ rows: [{ label: t('Total', '합계'), columns: { total: 'sum' as const, id: 'count' as const } }] }), [lang]);
return (
<div>
<div className="demo-controls">
<button type="button" onClick={() => setRows(makeRows(rows.length + 1000))}>
{t('Add 1,000 rows', '1,000행 추가')}
</button>
<button type="button" aria-pressed={theme === 'dark'} onClick={() => setTheme(theme === 'dark' ? 'light' : 'dark')}>
{t('Dark theme', '다크 테마')}
</button>
<button type="button" onClick={() => grid.current?.setSort([{ colId: 'total', dir: 'desc' }])}>
{t('Sort by total (ref API)', '합계 정렬 (ref API)')}
</button>
<span className="demo-note" style={{ margin: 0 }}>
{t(`${rows.length.toLocaleString()} rows · ${selected} selected`, `${rows.length.toLocaleString()}행 · ${selected}개 선택`)}
</span>
</div>
<FreeGrid
ref={grid}
className="demo-grid"
style={{ height: 480 }}
columns={columns}
data={rows}
theme={theme}
locale={lang}
rowSelection="multiple"
getRowId={row => String(row.id)}
summary={summary}
onCellClick={e => setClicked(`${e.colId}: ${String(e.value)}`)}
onSelectionChange={e => setSelected(e.selected.length)}
/>
<p className="demo-note">{clicked ? `onCellClick → ${clicked}` : t('Click any cell.', '아무 셀이나 클릭해 보세요.')}</p>
</div>
);
}