fix(web): смена ключа фильтра пар сбрасывает страницу в состоянии (M-13)
Возврат A→B→A даёт первую страницу, а не прежнюю. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
fb13389f75
commit
d230fb13ee
@ -8,7 +8,7 @@ import { getConsolidatedOsv } from '../../services/api/osv';
|
|||||||
import type { ConsolidatedRowOut, CounterPairOut, OsvFilters } from '../../types/api';
|
import type { ConsolidatedRowOut, CounterPairOut, OsvFilters } from '../../types/api';
|
||||||
import { CounterpartyMapModal } from './CounterpartyMapModal';
|
import { CounterpartyMapModal } from './CounterpartyMapModal';
|
||||||
import { group, money } from './OsvTable';
|
import { group, money } from './OsvTable';
|
||||||
import { clampPage, currentPage, missingSideEmptyText, pairLabel } from './counterPairs';
|
import { clampPage, missingSideEmptyText, pairLabel, syncPageState } from './counterPairs';
|
||||||
import { mapEntryId } from './counterpartyMapping';
|
import { mapEntryId } from './counterpartyMapping';
|
||||||
import { OSV_PAGE_SIZE, osvErrorText } from './useConsolidatedOsv';
|
import { OSV_PAGE_SIZE, osvErrorText } from './useConsolidatedOsv';
|
||||||
|
|
||||||
@ -38,8 +38,11 @@ function usePagedRows(versionId: string, filters: OsvFilters | null, reloadKey:
|
|||||||
const requestRef = useRef(0);
|
const requestRef = useRef(0);
|
||||||
const key = JSON.stringify(filters);
|
const key = JSON.stringify(filters);
|
||||||
// ключ и страница — одно состояние: смена фильтра даёт первую страницу и один запрос, а не два
|
// ключ и страница — одно состояние: смена фильтра даёт первую страницу и один запрос, а не два
|
||||||
const [pageState, setPageState] = useState({ key, page: 1 });
|
const [rawPageState, setPageState] = useState({ key, page: 1 });
|
||||||
const page = currentPage(pageState, key);
|
const pageState = syncPageState(rawPageState, key);
|
||||||
|
// ключ сменился — состояние сразу пересоздаётся (возврат к прежнему ключу не вернёт старую страницу)
|
||||||
|
if (pageState !== rawPageState) setPageState(pageState);
|
||||||
|
const page = pageState.page;
|
||||||
const setPage = useCallback((p: number) => setPageState({ key, page: p }), [key]);
|
const setPage = useCallback((p: number) => setPageState({ key, page: p }), [key]);
|
||||||
|
|
||||||
// biome-ignore lint/correctness/useExhaustiveDependencies: key — сериализованный filters; reloadKey — перечитать после сопоставления
|
// biome-ignore lint/correctness/useExhaustiveDependencies: key — сериализованный filters; reloadKey — перечитать после сопоставления
|
||||||
|
|||||||
@ -2,13 +2,13 @@ import { describe, expect, it } from 'vitest';
|
|||||||
import type { CounterPairOut } from '../../types/api';
|
import type { CounterPairOut } from '../../types/api';
|
||||||
import {
|
import {
|
||||||
clampPage,
|
clampPage,
|
||||||
currentPage,
|
|
||||||
missingSideEmptyText,
|
missingSideEmptyText,
|
||||||
pairLabel,
|
pairLabel,
|
||||||
pairsViewSearch,
|
pairsViewSearch,
|
||||||
readPairsView,
|
readPairsView,
|
||||||
selectPair,
|
selectPair,
|
||||||
switchPairsView,
|
switchPairsView,
|
||||||
|
syncPageState,
|
||||||
} from './counterPairs';
|
} from './counterPairs';
|
||||||
|
|
||||||
const pair = (holder: string, missing: string): CounterPairOut => ({
|
const pair = (holder: string, missing: string): CounterPairOut => ({
|
||||||
@ -96,14 +96,16 @@ describe('clampPage (T5.6)', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('currentPage (M-8)', () => {
|
describe('syncPageState (M-8, M-13)', () => {
|
||||||
it('ключ тот же — сохранённая страница', () => {
|
it('ключ тот же — состояние то же', () => {
|
||||||
expect(currentPage({ key: 'a', page: 3 }, 'a')).toBe(3);
|
const s = { key: 'a', page: 3 };
|
||||||
|
expect(syncPageState(s, 'a')).toBe(s);
|
||||||
});
|
});
|
||||||
it('ключ сменился — первая страница без отдельного обновления состояния', () => {
|
it('ключ сменился — {новый ключ, 1}', () => {
|
||||||
expect(currentPage({ key: 'a', page: 3 }, 'b')).toBe(1);
|
expect(syncPageState({ key: 'a', page: 3 }, 'b')).toEqual({ key: 'b', page: 1 });
|
||||||
});
|
});
|
||||||
it('вернулись к прежнему ключу после смены страницы под новым — страница нового', () => {
|
it('A (стр. 3) → B → A: снова первая страница, а не прежняя', () => {
|
||||||
expect(currentPage({ key: 'b', page: 2 }, 'b')).toBe(2);
|
const onB = syncPageState({ key: 'a', page: 3 }, 'b');
|
||||||
|
expect(syncPageState(onB, 'a')).toEqual({ key: 'a', page: 1 });
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -41,5 +41,6 @@ export const missingSideEmptyText = (p: CounterPairOut): string | null => {
|
|||||||
export const clampPage = (page: number, total: number, pageSize: number): number =>
|
export const clampPage = (page: number, total: number, pageSize: number): number =>
|
||||||
Math.min(page, Math.max(1, Math.ceil(total / pageSize)));
|
Math.min(page, Math.max(1, Math.ceil(total / pageSize)));
|
||||||
|
|
||||||
/** Страница, привязанная к ключу фильтра: другой ключ — первая страница сразу, без отдельного обновления состояния (один запрос). */
|
/** Состояние страницы под ключом фильтра: другой ключ — `{ключ, 1}`; прежнее состояние не хранится (A→B→A даёт первую страницу). */
|
||||||
export const currentPage = (state: { key: string; page: number }, key: string): number => (state.key === key ? state.page : 1);
|
export const syncPageState = (state: { key: string; page: number }, key: string): { key: string; page: number } =>
|
||||||
|
state.key === key ? state : { key, page: 1 };
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user