@sinequa/atomic

Text and paging

The search box and the pager — with the pagination fields the library computes for you, and the arithmetic not to write.

A search box and a pager. The only thing that needs care is reading pagination back, because two of the useful fields are computed by the library rather than sent by the server.

A search box with a pager

Search, page, and report the total
src/search-ui.ts
import { createAtomicClient } from "@sinequa/atomic";
import type { Query, Result, ResultPages } from "@sinequa/atomic";

const client = createAtomicClient({
  app: "<your-app>",
  backendUrl: "https://<your-sinequa-server>",
});

await client.initializeConfig();
await client.auth.login();

const state = { text: "", page: 1 };

export async function search(text: string) {
  // A new search always starts at page 1: keeping the page would show an empty
  // page 7 of a result set that now has two.
  state.text = text;
  state.page = 1;
  return run();
}

export async function goToPage(page: number) {
  state.page = page;
  return run();
}

async function run() {
  const query: Query = {
    name: "<your-query>",
    text: state.text,
    page: state.page,
    pageSize: 10,
  };

  // nextPage and previousPage are computed by the library and declared in the
  // return type, so an annotation is enough.
  const result: Result & ResultPages = await client.api.query.search(query);

  if (result.$error) throw result.$error;
  return result;
}

The pagination fields

Prop

Type

nextPage and previousPage come from resultPages(), which the library applies to every search response. It is exported, so you can apply it yourself to a result you obtained another way:

computing them from any response
import { resultPages } from "@sinequa/atomic";

const { nextPage, previousPage } = resultPages(result);

Why this is not left to the caller

Math.ceil(undefined / undefined) is NaN, and every comparison against NaN is false — so a response with no pagination read exactly like one on its last page. Both are now reported as undefined explicitly, which a falsy check handles correctly.

Accumulating pages instead of replacing them

For an infinite scroll, keep the pages you already have. Each record carries $page, so you can tell where it came from:

appending, not replacing
const next = await client.api.query.search({ ...base, page });

// $page is set by the library on every record.
records.push(...next.records);

Pitfalls

What's next

On this page