@alaarab/ogrid-react 2.1.0 → 2.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,10 +1,27 @@
1
- import { useState, useEffect, useCallback } from 'react';
1
+ import { useState, useEffect, useCallback, useRef } from 'react';
2
+ /** Shallow-compare two string arrays by value. */
3
+ function fieldsEqual(a, b) {
4
+ if (a.length !== b.length)
5
+ return false;
6
+ for (let i = 0; i < a.length; i++) {
7
+ if (a[i] !== b[i])
8
+ return false;
9
+ }
10
+ return true;
11
+ }
2
12
  /**
3
13
  * Load filter options for the given fields from a data source.
4
14
  *
5
15
  * Accepts `IDataSource<T>` or a plain `{ fetchFilterOptions }` object.
6
16
  */
7
17
  export function useFilterOptions(dataSource, fields) {
18
+ // Stabilize the fields array so inline literals (e.g. ['a','b']) don't
19
+ // cause infinite re-render loops via useCallback/useEffect deps.
20
+ const fieldsRef = useRef(fields);
21
+ if (!fieldsEqual(fieldsRef.current, fields)) {
22
+ fieldsRef.current = fields;
23
+ }
24
+ const stableFields = fieldsRef.current;
8
25
  const [filterOptions, setFilterOptions] = useState({});
9
26
  const [loadingOptions, setLoadingOptions] = useState({});
10
27
  const load = useCallback(async () => {
@@ -17,10 +34,10 @@ export function useFilterOptions(dataSource, fields) {
17
34
  return;
18
35
  }
19
36
  const loading = {};
20
- fields.forEach((f) => { loading[f] = true; });
37
+ stableFields.forEach((f) => { loading[f] = true; });
21
38
  setLoadingOptions(loading);
22
39
  const results = {};
23
- await Promise.all(fields.map(async (field) => {
40
+ await Promise.all(stableFields.map(async (field) => {
24
41
  try {
25
42
  results[field] = await fetcher(field);
26
43
  }
@@ -30,7 +47,7 @@ export function useFilterOptions(dataSource, fields) {
30
47
  }));
31
48
  setFilterOptions(results);
32
49
  setLoadingOptions({});
33
- }, [dataSource, fields]);
50
+ }, [dataSource, stableFields]);
34
51
  useEffect(() => {
35
52
  load().catch(() => { });
36
53
  }, [load]);
@@ -53,7 +53,6 @@ export function useOGrid(props, ref) {
53
53
  const dataFetchingState = useOGridDataFetching({
54
54
  isServerSide, dataSource, displayData, columns,
55
55
  stableFilters: filtersState.stableFilters,
56
- filters: filtersState.filters,
57
56
  sort: sortingState.sort,
58
57
  page: paginationState.page,
59
58
  pageSize: paginationState.pageSize,
@@ -5,7 +5,7 @@ import { processClientSideData } from '../utils';
5
5
  * Fires onFirstDataRendered once when items first appear.
6
6
  */
7
7
  export function useOGridDataFetching(params) {
8
- const { isServerSide, dataSource, displayData, columns, stableFilters, filters, sort, page, pageSize, onError, onFirstDataRendered, } = params;
8
+ const { isServerSide, dataSource, displayData, columns, stableFilters, sort, page, pageSize, onError, onFirstDataRendered, } = params;
9
9
  const isClientSide = !isServerSide;
10
10
  // --- Client-side filtering & sorting ---
11
11
  const clientItemsAndTotal = useMemo(() => {
@@ -35,7 +35,7 @@ export function useOGridDataFetching(params) {
35
35
  .fetchPage({
36
36
  page, pageSize,
37
37
  sort: { field: sort.field, direction: sort.direction },
38
- filters,
38
+ filters: stableFilters,
39
39
  })
40
40
  .then((res) => {
41
41
  if (id !== fetchIdRef.current)
@@ -54,7 +54,7 @@ export function useOGridDataFetching(params) {
54
54
  if (id === fetchIdRef.current)
55
55
  setServerLoading(false);
56
56
  });
57
- }, [isServerSide, dataSource, page, pageSize, sort.field, sort.direction, filters, onError, refreshCounter]);
57
+ }, [isServerSide, dataSource, page, pageSize, sort.field, sort.direction, stableFilters, onError, refreshCounter]);
58
58
  const displayItems = isClientSide && clientItemsAndTotal ? clientItemsAndTotal.items : serverItems;
59
59
  const displayTotalCount = isClientSide && clientItemsAndTotal ? clientItemsAndTotal.totalCount : serverTotalCount;
60
60
  // Fire onFirstDataRendered once when the grid first has data
@@ -6,7 +6,6 @@ export interface UseOGridDataFetchingParams<T> {
6
6
  displayData: T[];
7
7
  columns: ICoreColumnDef<T>[];
8
8
  stableFilters: IFilters;
9
- filters: IFilters;
10
9
  sort: {
11
10
  field: string;
12
11
  direction: 'asc' | 'desc';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alaarab/ogrid-react",
3
- "version": "2.1.0",
3
+ "version": "2.1.1",
4
4
  "description": "OGrid React – React hooks, headless components, and utilities for OGrid data grids.",
5
5
  "main": "dist/esm/index.js",
6
6
  "module": "dist/esm/index.js",
@@ -36,7 +36,7 @@
36
36
  "node": ">=18"
37
37
  },
38
38
  "dependencies": {
39
- "@alaarab/ogrid-core": "2.1.0"
39
+ "@alaarab/ogrid-core": "2.1.1"
40
40
  },
41
41
  "peerDependencies": {
42
42
  "@tanstack/react-virtual": "^3.0.0",