Tech TutorBangla Web Documentation
Portfolio
HomeHTMLCSSTailwind CSSJavaScriptTypeScriptReactNext.jsNode.jsExpressSocket.IOExpoWordPressPostgreSQLPrismaPostgresNestJSMongoDBDockerTanStackTanStack TableRTK QueryGitGitHub
  • TanStack Table Documentation12টি অধ্যায়
প্রযুক্তি নির্বাচন
HomeHTMLCSSTailwind CSSJavaScriptTypeScriptReactNext.jsNode.jsExpressSocket.IOExpoWordPressPostgreSQLPrismaPostgresNestJSMongoDBDockerTanStackTanStack TableRTK QueryGitGitHub
  • Introduction
  • Installation & Setup
  • Core Concepts
  • Column Definitions
  • Row Models
  • Sorting
  • Filtering
  • Pagination
  • Row Selection
  • Column Management
  • Server-side Mode
  • Advanced Features
  1. Docs
  2. TanStack Table
  3. মূল ধারণা — useReactTable ও row/cell/column
TanStack TableBeginner

মূল ধারণা — useReactTable ও row/cell/column

useReactTable-এর option, table/row/cell/column ইনস্ট্যান্স, flexRender-এর context, controlled বনাম uncontrolled state — বাংলায়।

31টি অংশবাংলা ভাষায়

আগের অধ্যায়ে একটা কাজ করা টেবিল দেখলাম। এখন সেই কোডের পিছনের যুক্তিটা বোঝা যাক — কেন getCoreRowModel লাগে, row জিনিসটা আসলে কী, আর flexRender-এর ভেতরে কী পাওয়া যায়।

useReactTable — একটি কেন্দ্রীয় hook

options-এর পাঁচটি ভাগtsx
tsx
const table = useReactTable({
  // ১. কী দেখাবো
  data,
  columns,

  // ২. এখন কোন অবস্থায় আছে (controlled)
  state: { sorting, pagination },
  onSortingChange: setSorting,
  onPaginationChange: setPagination,

  // ৩. শুরুর অবস্থা (uncontrolled)
  initialState: { pagination: { pageSize: 10 } },

  // ৪. কীভাবে transform হবে
  getCoreRowModel: getCoreRowModel(),
  getSortedRowModel: getSortedRowModel(),

  // ৫. কোনো কাজ কি আমি নিজে করব
  manualSorting: false,
});

এই একটি hook থেকে যা পাওয়া যায় তা table — এর উপর রয়েছে সব state ও action। এটা একটা state machine-এর মতো: অবস্থা বদলালে React নিজে থেকেই নতুন করে হিসাব করে।

table-এর উপর যা আছে

table APItypescript
typescript
// state পড়া
table.getState()               // { sorting, pagination, globalFilter, ... }
table.getState().sorting       // SortingState

// একটি row model-এর ফলাখানা
table.getRowModel().rows       // ← রেন্ডারে এটাই ব্যবহার হয়
table.getCoreRowModel().rows   // raw data থেকে তৈরি মূল row
table.getSortedRowModel().rows // সাজানো row
table.getSelectedRowModel().rows

// কলাম খুঁজে বের করা
const priceCol = table.getColumn("price");
priceCol.getIsVisible()

// column visibility
table.getAllLeafColumns()
table.getVisibleLeafColumns()

// পেজ সংক্রান্ত
table.getCanNextPage()
table.getPageCount()

নিয়মটা সহজ: যা পড়তে চান সব get*, যা বদলাতে চান সব set*/toggle*, আর যা DOM-এর সাথে জুড়ে দেওয়ার কাজ (event handler) তার নাম get*Handler() দিয়ে শুরু হয়।

Row ইনস্ট্যান্স — একটি row-এর সব তথ্য

row APItypescript
typescript
table.getRowModel().rows.map((row) => {
  row.id             // "p-01" (getRowId দিলে) বা index "0"
  row.index          // মূল ডেটার index
  row.original       // ← আপনার মূল Product অবজেক্ট

  row.getVisibleCells()   // লুকানো কলাম বাদ দিয়ে cell
  row.getAllCells()       // সব cell
  row.getCell("price")   // নির্দিষ্ট কলামের cell

  // sub-row (row expanding)
  row.getLeafRows()
  row.getParentRow()
  row.subRows
  row.getCanExpand()

  return null;
})}

row.original হলো আপনার ডেটা। বাকি সব TanStack-এর হিসাব করা অবজেক্ট। কোনো সময় row.original.name লিখতে ভুলে row.name লিখে ফেললে সেটা ভুল লাগবে — row এর নিজস্ব property নেই, এগুলো get* method।

row.original.name, নাকি row.getValue("name")?

দুটোই কাজ করে, কিন্তু row.original দ্রুত ও টাইপ-সেফ — row টাইপ Product, তাই original-এর property ভুল লিখলে কম্পাইলার ধরে। row.getValue("price") লিখলে কিন্তু price স্ট্রিং হিসেবে গোনে, তাই + 1 করলে concat হয়ে যায়। সংখ্যা নিয়ে কাজ করলে getValue ব্যবহার করে Number(...) করুন।

Cell ও Column ইনস্ট্যান্স

cell APItypescript
typescript
const cell = row.getCell("price");

cell.id              // `${row.id}_price` — key হিসেবে ব্যবহার্য
cell.column          // ← এই cell-এর ColumnDef
cell.row             // ← কোন row-এ পড়ছে
cell.getValue()      // মান (accessor বা cell renderer ছাড়া)
cell.renderValue()   // মান render করে (JSX)
cell.getIsPlaceholder()
cell.getContext()    // ← flexRender-এ যা যায়
column APItypescript
typescript
const column = table.getColumn("price");

column.id
column.columnDef        // ← আপনার লেখা ColumnDef অবজেক্ট
column.getIsVisible()
column.getCanHide()
column.getCanSort()
column.getIsSorted()
column.getSortDirection()
column.getToggleSortingHandler()
column.getFacetedUniqueValues() // filter-এর জন্য অপশন তালিকা
column.getFacetedRowModel()

getContext()-এ যা থাকে: table, column, row, cell, staticRowIndex, staticColumnIndex। মানে cell: ({ row, table, getValue }) => … — এই সব parameter এখান থেকেই আসে।

flexRender — header ও cell রেন্ডারের সেতু

ColumnDef-এ header ও cell যেকোনো একটা ফর্মে লেখা যায় — string, function, বা component। flexRender সেটা ঠিকঠাক context দিয়ে render করে।

import { flexRender } from "@tanstack/react-table";

// columnDef: { header: "মূল্য" }        → string
// columnDef: { header: ({ column }) => … }  → function
// columnDef: { cell: PriceCell }            → component
flexRender(header.column.columnDef.header, header.getContext());
লেখার ধরনউদাহরণকখন ব্যবহার
stringheader: "নাম"শুধু লেখা দেখাতে
functioncell: ({ row }) => row.original.nameডেটা থেকে কিছু বানাতে
ReactNodeheader: <span>মূল্য</span>markup দরকার হলে
component refcell: PriceCellপুনঃব্যবহারযোগ্য UI

function-এর getValue() ব্যবহার করা ভালো — কারণ accessorKey-র নাম বদলালেও কোড ভাঙে না, আর টাইপও ইনফার করা যায়।

controlled বনাম uncontrolled state

এটা React-এর পরিচিত নিয়ম, TanStack-এও হুবহু একই।

দুই ধরনের statetsx
tsx
// Uncontrolled — table নিজের মধ্যে state ধরে রাখে
useReactTable({
  columns,
  data,
  getCoreRowModel: getCoreRowModel(),
  initialState: { pagination: { pageSize: 20 } },
})

// Controlled — state আমাদের কাছে, আমরাই বদলাই
const [pagination, setPagination] = useState({ pageIndex: 0, pageSize: 10 });

useReactTable({
  columns,
  data,
  getCoreRowModel: getCoreRowModel(),
  getPaginationRowModel: getPaginationRowModel(),
  state: { pagination },      // ← আমরা দিচ্ছি
  onPaginationChange: setPagination, // ← আমরাই বদলাবো
})
UncontrolledControlled
কে ধরে রাখেtable নিজেআপনি
কীভাবে শুরুinitialStateuseState
কীভাবে বদলেtable নিজেon*Change handler
URL-এ দেখানো যায়নাহ্যাঁ
Query-এর সাথে যুক্তকঠিনসহজ

প্রায় সব real অ্যাপে controlled লাগবে — কারণ sorting/filtering/pagination অবস্থা server-এর query param হিসেবেও যেতে হয় (অধ্যায় ১১)। তবে columnVisibility, rowSelection-এর মতো UI-only state uncontrolled রাখলেও চলে।

ছোট একটা পরীক্ষা

console দিয়ে যাচাইtypescript
typescript
const table = useReactTable({
  data: mockProducts,
  columns,
  getCoreRowModel: getCoreRowModel(),
});

// DevTools-এ বা console-এ লিখে দেখুন
console.log(table.getRowModel().rows.length);      // ১২
console.log(table.getAllLeafColumns().map((c) => c.id)); // ["name","price"]
console.log(table.getRowModel().rows[0].original);  // প্রথম Product অবজেক্ট
row.id ডিফল্টে index

getRowId: (row) => row.id না দিলে row.id মানে হয় row-এর index — "0", "1", "2"। ডেটা সাজালে বা filter বদলালে index বদলে যায়, ফলে selection ভেঙে যায়। getRowId কেন এত জরুরি, তা অধ্যায় ৫ ও ৯-এ বিস্তারিত।

সারসংক্ষেপ

  • useReactTable = একটি hook → table instance
  • table.getRowModel() রেন্ডারের জন্য; বাকি get*RowModel() debug/হিসাবে
  • row.original আপনার ডেটা, বাকি সব computed
  • flexRender(def, context) = যেকোনো ধরনের header/cell render করার একটাই উপায়
  • state controlled রাখলে URL ও Query-এর সাথে জোড়া লাগানো সহজ

পরের অধ্যায়ে columns নিয়ে বিস্তারিত — accessorKey, accessorFn, id, cell, meta এবং একটা কলামের সব option।

শেষ প্যারায় নিজে practice করুন — কোড কপি করে নিজের এডিটরে চালিয়ে দেখুন।
আগেরইনস্টলেশন ও প্রজেক্ট সেটআপপরেরColumnDef — কলাম সংজ্ঞা
এই পেজে
Tech Tutor

বাংলায় ওয়েব ডেভেলপমেন্ট ডকুমেন্টেশন শিখুন — ধাপে ধাপে।

Homeসব ডকুমেন্টেশনQuick Startআমার নোটস

© 2026 Tech Tutor. বাংলায় শিখুন, বাংলায় গড়ুন।

mdanamolhasan1998@gmail.com