From 781b9a24dfa2b15c327471b67aaa05c9ee9dd922 Mon Sep 17 00:00:00 2001 From: Joel Davies Date: Wed, 15 Jan 2025 14:10:02 +0000 Subject: [PATCH 1/2] Initial attempted fix #1259 --- src/App.tsx | 3 +- src/common/preservedTableState.component.tsx | 63 ++++++++++++++++++-- 2 files changed, 60 insertions(+), 6 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index ec3eafe08..a51e81406 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -272,8 +272,7 @@ export default function App() { ); diff --git a/src/common/preservedTableState.component.tsx b/src/common/preservedTableState.component.tsx index 4e6a59ec8..70e22bae9 100644 --- a/src/common/preservedTableState.component.tsx +++ b/src/common/preservedTableState.component.tsx @@ -185,18 +185,29 @@ export const usePreservedTableState = (props?: UsePreservedTableStateProps) => { // Keeps track of the last location state update to occur (for detecting browser changes e.g. back button being clicked) const lastLocationUpdate = useRef(location); + const searchParamsFromWindow = new URLSearchParams(window.location.search); const urlParamName = props?.urlParamName || 'state'; + const log = (value: unknown) => console.log(value + `[${urlParamName}]`); const compressedState = props?.storeInUrl - ? searchParams.get(urlParamName) + ? searchParamsFromWindow.get(urlParamName) : null; const unparsedState = decompressState(compressedState); const [parsedState, setParsedState] = useState( getParsedState(unparsedState) ); + log('---------- NEW RENDER ---------'); + log('Search params: ' + searchParams.toString()); + log('Search params 2: ' + searchParamsFromWindow.toString()); + log(window.location.search); + log('Unparsed state ' + unparsedState + ' (render)'); + log('Parsed state ' + Object.entries(parsedState) + ' (render)'); // Update the search params only if necessary useEffect(() => { + log('HERE'); + log(window.location.search); + log(location.search); if (props?.storeInUrl) { // Get the expected unparsed state in the URL for the current internal state const parsedStateSearchParams = convertInternalState(parsedState); @@ -212,14 +223,48 @@ export const usePreservedTableState = (props?: UsePreservedTableStateProps) => { ) { // Clear search params if state is no longer needed if (newUnparsedState !== '{}') { - searchParams.set( + log('Updating search params (useEffect)'); + log('New state: ' + newUnparsedState); + log('Existing search params: ' + searchParamsFromWindow.toString()); + searchParamsFromWindow.set( urlParamName, LZString.compressToEncodedURIComponent(newUnparsedState) ); - setSearchParams(searchParams, { replace: false }); + log('New search params: ' + searchParamsFromWindow.toString()); + setSearchParams(searchParamsFromWindow, { replace: false }); + + // setSearchParams( + // (prev) => { + // console.log(prev.entries()); + // const next = new URLSearchParams( + // Object.fromEntries(prev.entries()) + // ); + // console.log(next.entries()); + // next.set( + // urlParamName, + // LZString.compressToEncodedURIComponent(newUnparsedState) + // ); + // console.log(newUnparsedState); + // console.log(next.toString()); + // return next; + // }, + // { replace: false } + // ); } else { + log('Clearing search params (useEffect)'); searchParams.delete(urlParamName); setSearchParams(searchParams, { replace: false }); + + // setSearchParams( + // (prev) => { + // const next = new URLSearchParams( + // Object.fromEntries(prev.entries()) + // ); + // next.delete(urlParamName); + // return next; + // }, + // { replace: false } + // ); } } else { // Update the internal state to reflect the browser level change @@ -229,6 +274,10 @@ export const usePreservedTableState = (props?: UsePreservedTableStateProps) => { if (lastLocationUpdate.current.pathname !== location.pathname) firstUpdate.current.p = undefined; + log( + 'Updating internal state to reflect browser level change (useEffect)' + ); + setParsedState(getParsedState(unparsedState)); } } @@ -239,7 +288,7 @@ export const usePreservedTableState = (props?: UsePreservedTableStateProps) => { location, parsedState, props?.storeInUrl, - searchParams, + searchParamsFromWindow, setSearchParams, unparsedState, urlParamName, @@ -540,6 +589,12 @@ export const usePreservedTableState = (props?: UsePreservedTableStateProps) => { updaterOrValue, prevState.p || defaultState.p ); + log( + 'Updating internal params: ' + + newValue.pageIndex + + ' ' + + newValue.pageSize + ); return { ...prevState, p: From f365b553fed15f62ecb50502bef2b234bf9fabf1 Mon Sep 17 00:00:00 2001 From: Joel Davies Date: Thu, 16 Jan 2025 08:53:00 +0000 Subject: [PATCH 2/2] Changes for debugging #1259 --- cypress/e2e/with_mock_data/systems.cy.ts | 2 +- package.json | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cypress/e2e/with_mock_data/systems.cy.ts b/cypress/e2e/with_mock_data/systems.cy.ts index 5dcc2e6ad..3a9c80364 100644 --- a/cypress/e2e/with_mock_data/systems.cy.ts +++ b/cypress/e2e/with_mock_data/systems.cy.ts @@ -129,7 +129,7 @@ describe('Systems', () => { cy.location('search').should('eq', ''); }); - it('should be able to navigate through subsystems while preserving the table states when going back', () => { + it.only('should be able to navigate through subsystems while preserving the table states when going back', () => { cy.visit('/systems/65328f34a40ff5301575a4e3'); cy.findByText('Smaller laser').should('be.visible'); diff --git a/package.json b/package.json index 2bad6cc3c..5b8b46870 100644 --- a/package.json +++ b/package.json @@ -58,9 +58,9 @@ "preview:build:dev": "yarn build --watch & yarn preview", "test": "vitest --coverage", "lint": "eslint --max-warnings=0 --fix ./src ./cypress && tsc --noEmit && tsc --noEmit -p cypress/tsconfig.json", - "build:e2e": "cross-env VITE_APP_BUILD_STANDALONE=true VITE_APP_INCLUDE_MSW=true GENERATE_SOURCEMAP=false yarn build", + "build:e2e": "cross-env VITE_APP_BUILD_STANDALONE=true VITE_APP_INCLUDE_MSW=true GENERATE_SOURCEMAP=false yarn build --watch", "build:e2e:api": "cross-env VITE_APP_BUILD_STANDALONE=true VITE_APP_INCLUDE_MSW=false GENERATE_SOURCEMAP=false yarn build", - "e2e:serve": "yarn build:e2e && node ./server/e2e-test-server.js", + "e2e:serve": "yarn build:e2e & node ./server/e2e-test-server.js", "e2e:serve:api": "yarn build:e2e:api && node ./server/e2e-test-server.js", "e2e:interactive": "start-server-and-test e2e:serve http://localhost:3000 cy:open", "e2e:interactive:api": "start-server-and-test e2e:serve:api http://localhost:3000 cy:open",