Fix manifest list create/edit navigation after Vite HMR.

Keep a single browser router across hot reloads and drive ManifestList/Form via withNavigate instead of a stale router.navigate singleton.
This commit is contained in:
seb
2026-08-06 22:47:51 +02:00
parent 4896b1dc36
commit 628980dc49
3 changed files with 38 additions and 18 deletions

View File

@@ -26,7 +26,7 @@ const KundeGruppenPage = lazy(() => import('./pages/kunde/gruppen'));
const KundeEditPage = lazy(() => import('./pages/kunde/edit')); const KundeEditPage = lazy(() => import('./pages/kunde/edit'));
const InfosPage = lazy(() => import('./pages/infos/index')); const InfosPage = lazy(() => import('./pages/infos/index'));
export const router = createBrowserRouter([ const routes = [
{ {
path: '/', path: '/',
element: <AppShell />, element: <AppShell />,
@@ -64,14 +64,9 @@ export const router = createBrowserRouter([
children: [ children: [
{ index: true, element: <AuftragAngebotPage /> }, { index: true, element: <AuftragAngebotPage /> },
{ path: 'neu', element: <AuftragAngebotNeuPage /> }, { path: 'neu', element: <AuftragAngebotNeuPage /> },
{ { path: 'bestellung', element: <AuftragBestellungPage /> },
path: 'bestellung', { path: 'bestellung/neu', element: <AuftragBestellungNeuPage /> },
children: [ { path: 'bestellung/:orderId', element: <AuftragBestellungEditPage /> },
{ index: true, element: <AuftragBestellungPage /> },
{ path: 'neu', element: <AuftragBestellungNeuPage /> },
{ path: ':orderId', element: <AuftragBestellungEditPage /> },
],
},
{ path: 'ausliefern', element: <AuftragAusliefernPage /> }, { path: 'ausliefern', element: <AuftragAusliefernPage /> },
{ path: 'retoure', element: <AuftragRetourePage /> }, { path: 'retoure', element: <AuftragRetourePage /> },
{ path: ':quoteId', element: <AuftragAngebotEditPage /> }, { path: ':quoteId', element: <AuftragAngebotEditPage /> },
@@ -90,4 +85,12 @@ export const router = createBrowserRouter([
{ path: '*', element: <Navigate to="/artikel" replace /> }, { path: '*', element: <Navigate to="/artikel" replace /> },
], ],
}, },
]); ];
/** Keep one router across Vite HMR — recreating breaks navigate()/Link mid-session. */
export const router =
import.meta.hot?.data?.router ?? createBrowserRouter(routes);
if (import.meta.hot) {
import.meta.hot.data.router = router;
}

View File

@@ -6,10 +6,10 @@ import { enqueueSnackbar } from 'notistack';
import BackendError from '../BackendError'; import BackendError from '../BackendError';
import { PanelTile, PanelTileGrid } from '../panels'; import { PanelTile, PanelTileGrid } from '../panels';
import { StorageManagerContext } from '../../api/storageManagerContext'; import { StorageManagerContext } from '../../api/storageManagerContext';
import { router } from '../../appRouter';
import { requireArray, requireDefined, requireObject } from '../../utils/apiShape'; import { requireArray, requireDefined, requireObject } from '../../utils/apiShape';
import { backendErrorFrom } from '../../utils/backendError'; import { backendErrorFrom } from '../../utils/backendError';
import { notifyError } from '../../utils/notify'; import { notifyError } from '../../utils/notify';
import withNavigate from '../withNavigate';
import ManifestHeader from './ManifestHeader'; import ManifestHeader from './ManifestHeader';
import ManifestLines from './ManifestLines'; import ManifestLines from './ManifestLines';
import { import {
@@ -209,7 +209,7 @@ class ManifestForm extends PureComponent {
await this.context[cfg.updateCache](); await this.context[cfg.updateCache]();
if (this._cancelled) return; if (this._cancelled) return;
enqueueSnackbar(cfg.createdMsg, { variant: 'success' }); enqueueSnackbar(cfg.createdMsg, { variant: 'success' });
void router.navigate(cfg.editPath(data[cfg.docField].id)); this.props.navigate(cfg.editPath(data[cfg.docField].id));
return; return;
} }
@@ -318,4 +318,4 @@ class ManifestForm extends PureComponent {
} }
} }
export default ManifestForm; export default withNavigate(ManifestForm);

View File

@@ -17,9 +17,9 @@ import { enqueueSnackbar } from 'notistack';
import BackendError from '../BackendError'; import BackendError from '../BackendError';
import { PanelTile, PanelTileGrid } from '../panels'; import { PanelTile, PanelTileGrid } from '../panels';
import { StorageManagerContext } from '../../api/storageManagerContext'; import { StorageManagerContext } from '../../api/storageManagerContext';
import { router } from '../../appRouter';
import { backendErrorFrom } from '../../utils/backendError'; import { backendErrorFrom } from '../../utils/backendError';
import { notifyError } from '../../utils/notify'; import { notifyError } from '../../utils/notify';
import withNavigate from '../withNavigate';
import { import {
formatDate, formatDate,
loadParties, loadParties,
@@ -79,12 +79,22 @@ class ManifestList extends PureComponent {
void this.load(); void this.load();
} }
/** Same path as AppShell sub-nav: live useNavigate via withNavigate. */
go(to) {
const { navigate } = this.props;
if (typeof navigate === 'function') {
navigate(to);
return;
}
window.location.assign(to);
}
handleCreate() { handleCreate() {
void router.navigate(this.cfg.createPath); this.go(this.cfg.createPath);
} }
handleEdit(doc) { handleEdit(doc) {
void router.navigate(this.cfg.editPath(doc.id)); this.go(this.cfg.editPath(doc.id));
} }
async handleDelete(doc) { async handleDelete(doc) {
@@ -139,7 +149,12 @@ class ManifestList extends PureComponent {
<PanelTile wide={3} minHeight={240} color={cfg.listColor}> <PanelTile wide={3} minHeight={240} color={cfg.listColor}>
<Stack spacing={2}> <Stack spacing={2}>
<Box sx={{ display: 'flex', justifyContent: 'flex-end' }}> <Box sx={{ display: 'flex', justifyContent: 'flex-end' }}>
<Button variant="contained" size="small" onClick={this.handleCreate}> <Button
type="button"
variant="contained"
size="small"
onClick={this.handleCreate}
>
{cfg.createButton} {cfg.createButton}
</Button> </Button>
</Box> </Box>
@@ -175,6 +190,7 @@ class ManifestList extends PureComponent {
onClick={(e) => e.stopPropagation()} onClick={(e) => e.stopPropagation()}
> >
<IconButton <IconButton
type="button"
size="small" size="small"
aria-label={`„${row.number}“ bearbeiten`} aria-label={`„${row.number}“ bearbeiten`}
onClick={() => this.handleEdit(row)} onClick={() => this.handleEdit(row)}
@@ -182,6 +198,7 @@ class ManifestList extends PureComponent {
<EditOutlinedIcon fontSize="small" /> <EditOutlinedIcon fontSize="small" />
</IconButton> </IconButton>
<IconButton <IconButton
type="button"
size="small" size="small"
aria-label={`„${row.number}“ löschen`} aria-label={`„${row.number}“ löschen`}
disabled={busyId != null} disabled={busyId != null}
@@ -203,4 +220,4 @@ class ManifestList extends PureComponent {
} }
} }
export default ManifestList; export default withNavigate(ManifestList);