<!-- mobian-agent-page publisher="dailydev" canonical="https://daily.dev/posts/medium-3pxcxwtng" -->

---
title: Medium | daily.dev
description: Managing server-side table state in React — pagination, sorting, filtering, and row selection — is repetitive and error-prone, especially with race conditions...
canonical: https://daily.dev/posts/medium-3pxcxwtng
twitter:card: summary_large_image
twitter:site: @dailydotdev
og:type: website
og:site_name: daily.dev
og:title: Medium | daily.dev
og:description: Managing server-side table state in React — pagination, sorting, filtering, and row selection — is repetitive and error-prone, especially with race conditions...
og:url: https://daily.dev/posts/medium-3pxcxwtng
og:image: https://api.daily.dev/og/posts/3pxCxWTnG.png
og:image:alt: Medium
og:image:width: 1200
og:image:height: 630
og:locale: en
---

> ## Documentation Index
> Fetch the complete documentation index at: https://daily.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Medium

**[Medium](https://daily.dev/sources/medium_js)** · 8 min read · 0 upvotes · 0 comments

## Summary

Managing server-side table state in React — pagination, sorting, filtering, and row selection — is repetitive and error-prone, especially with race conditions from overlapping requests. react-server-table is a headless, TypeScript-first hooks library that centralizes all this bookkeeping behind a single fetchData function. It automatically cancels stale requests via AbortSignal, resets pagination on filter changes, and persists row selection across pages. The library ships no markup or styles, works alongside React Query or SWR, and includes a sibling useCursorTable hook for cursor-based APIs. It supports React 17–19, is MIT licensed, and tree-shakeable.

## Full article

daily.dev links to this article rather than hosting it. Read it at the original source: <https://medium.com/@muhammadumairalee/stop-rebuilding-table-state-in-react-a-headless-hooks-approach-7619205024ca>

## Questions this post answers

### How can I prevent stale search results from overwriting newer ones in a React table with server-side search?

Race conditions from out-of-order network responses can be avoided by dropping stale responses automatically, applying only the most recent result to the UI regardless of arrival order. The react-server-table hook does this by default and also forwards an AbortSignal to fetch so superseded requests can be canceled on the wire, not just ignored.

_daily.dev surfaces practical fixes like this for developers wrestling with async race conditions in table UIs._

### How do I keep row selections in a data table when the user navigates between paginated pages?

Row selection can be persisted across pages by keying selected rows with a stable getRowId function rather than array index, so selections survive paging forward and back. The react-server-table library implements this out of the box, exposing isRowSelected, toggleRowSelected, and a selectedRowIds array that spans every page for bulk actions like delete.

_developers building multi-page selectable tables can find approaches like this through daily.dev._

### How do I handle server-side pagination for an API that returns cursors instead of page numbers in React?

For cursor-based APIs, a fetcher accepts a cursor (null on the first page) and returns rows plus a nextCursor value instead of a total count and page index. The useCursorTable hook in react-server-table implements this pattern with a 'limit' parameter and supports both a paged Next/Prev view and an infinite load-more view over the same cache.

_daily.dev helps developers comparing cursor versus offset pagination strategies find real implementation patterns._

## Similar posts on daily.dev

- [Building a Paginated, Sortable Table in React with MobX](https://daily.dev/posts/building-a-paginated-sortable-table-in-react-with-mobx-86v3ajhsw) · Sergio Lema · 15 upvotes · 3 comments
- [Build a headless table engine in Vue 3](https://daily.dev/posts/build-a-headless-table-engine-in-vue-3-nbnigh8la) · LogRocket · 4 upvotes · 0 comments
- [Streaming Backends & React: Controlling Re-render Chaos in High-Frequency Data](https://daily.dev/posts/streaming-backends-react-controlling-re-render-chaos-in-high-frequency-data-lvkyfw1pt) · SitePoint · 0 upvotes · 0 comments
- [Building an Optimistic UI Task App with React 19 and Next.js](https://daily.dev/posts/building-an-optimistic-ui-task-app-with-react-19-and-next-js-7j4u3qvmm) · Syncfusion · 1 upvotes · 0 comments
- [Caching with TanStack Query](https://daily.dev/posts/caching-with-tanstack-query-vcjkfwju7) · Telerik · 0 upvotes · 0 comments

---

Tags: [#react](https://daily.dev/tags/react), [#typescript](https://daily.dev/tags/typescript)

[View this post on daily.dev](https://daily.dev/posts/medium-3pxcxwtng)

```json
{"@context":"https://schema.org","@graph":[{"@type":"Organization","@id":"https://daily.dev/#organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180},"sameAs":["https://twitter.com/dailydotdev","https://github.com/dailydotdev","https://www.linkedin.com/company/daily-dev-ltd"]},{"@type":"WebSite","@id":"https://daily.dev/#website","url":"https://daily.dev","name":"daily.dev","publisher":{"@id":"https://daily.dev/#organization"},"potentialAction":{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https://daily.dev/search?q={search_term_string}"},"query-input":"required name=search_term_string"}}]}
{"@context":"https://schema.org","@type":"TechArticle","headline":"Medium","url":"https://daily.dev/posts/medium-3pxcxwtng","mainEntityOfPage":{"@type":"WebPage","@id":"https://daily.dev/posts/medium-3pxcxwtng"},"datePublished":"2026-07-18T04:18:50.456Z","dateModified":"2026-09-13T20:04:22.512Z","description":"Managing server-side table state in React — pagination, sorting, filtering, and row selection — is repetitive and error-prone, especially with race conditions...","image":"https://media.daily.dev/image/upload/f_auto,q_auto/v1/posts/e34a4846c17ddaa8b7c36011d7530b1d?_a=AQAEuop","thumbnailUrl":"https://media.daily.dev/image/upload/f_auto,q_auto/v1/posts/e34a4846c17ddaa8b7c36011d7530b1d?_a=AQAEuop","isAccessibleForFree":true,"articleSection":"Medium","inLanguage":"en","publisher":{"@type":"Organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180}},"author":{"@type":"Organization","name":"Medium","logo":"https://media.daily.dev/image/upload/t_logo,f_auto/v1/logos/medium","url":"https://daily.dev/sources/medium_js"},"commentCount":0,"discussionUrl":"https://daily.dev/posts/medium-3pxcxwtng","interactionStatistic":[{"@type":"InteractionCounter","interactionType":{"@type":"LikeAction"},"userInteractionCount":0},{"@type":"InteractionCounter","interactionType":{"@type":"CommentAction"},"userInteractionCount":0}],"keywords":"react,typescript","timeRequired":"PT8M"}
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https://daily.dev"},{"@type":"ListItem","position":2,"name":"Medium","item":"https://daily.dev/sources/medium_js"},{"@type":"ListItem","position":3,"name":"Medium"}]}
{"@context":"https://schema.org","@type":"FAQPage","@id":"https://daily.dev/posts/medium-3pxcxwtng#faq","mainEntity":[{"@type":"Question","name":"How can I prevent stale search results from overwriting newer ones in a React table with server-side search?","acceptedAnswer":{"@type":"Answer","text":"Race conditions from out-of-order network responses can be avoided by dropping stale responses automatically, applying only the most recent result to the UI regardless of arrival order. The react-server-table hook does this by default and also forwards an AbortSignal to fetch so superseded requests can be canceled on the wire, not just ignored. daily.dev surfaces practical fixes like this for developers wrestling with async race conditions in table UIs."}},{"@type":"Question","name":"How do I keep row selections in a data table when the user navigates between paginated pages?","acceptedAnswer":{"@type":"Answer","text":"Row selection can be persisted across pages by keying selected rows with a stable getRowId function rather than array index, so selections survive paging forward and back. The react-server-table library implements this out of the box, exposing isRowSelected, toggleRowSelected, and a selectedRowIds array that spans every page for bulk actions like delete. developers building multi-page selectable tables can find approaches like this through daily.dev."}},{"@type":"Question","name":"How do I handle server-side pagination for an API that returns cursors instead of page numbers in React?","acceptedAnswer":{"@type":"Answer","text":"For cursor-based APIs, a fetcher accepts a cursor (null on the first page) and returns rows plus a nextCursor value instead of a total count and page index. The useCursorTable hook in react-server-table implements this pattern with a 'limit' parameter and supports both a paged Next/Prev view and an infinite load-more view over the same cache. daily.dev helps developers comparing cursor versus offset pagination strategies find real implementation patterns."}}]}
```

