fix(17): WR-05 IN-03 IN-01 resize-aware useIsPhone hook; OidcRedirect side-effect in effect
This commit is contained in:
@@ -44,7 +44,7 @@
|
||||
* - /api/me query shared so AppNav has user data on all routes.
|
||||
*/
|
||||
|
||||
import { useState, useMemo } from 'react';
|
||||
import { useState, useMemo, useEffect } from 'react';
|
||||
import { BrowserRouter, Routes, Route, Navigate } from 'react-router';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { CalendarShell } from './components/CalendarShell.js';
|
||||
@@ -59,12 +59,9 @@ import { PushPermissionPrompt } from './components/PushPermissionPrompt.js';
|
||||
import { PermissionDeniedBanner } from './components/PermissionDeniedBanner.js';
|
||||
import { SetupBanner } from './components/SetupBanner.js';
|
||||
import { SettingsSheet } from './components/SettingsSheet.js';
|
||||
import { useIsPhone } from './hooks/useIsPhone.js';
|
||||
import { fetchMe, fetchSetupStatus, fetchAuthMode } from './api/client.js';
|
||||
|
||||
function isPhone(): boolean {
|
||||
return typeof window !== 'undefined' && window.matchMedia('(max-width: 767px)').matches;
|
||||
}
|
||||
|
||||
/**
|
||||
* OidcRedirect — tiny helper that triggers a top-level navigation to /api/login.
|
||||
*
|
||||
@@ -75,13 +72,18 @@ function isPhone(): boolean {
|
||||
* which browsers cannot follow as a fetch/XHR (T-07-04).
|
||||
*/
|
||||
function OidcRedirect() {
|
||||
window.location.replace('/api/login');
|
||||
// IN-01: navigate from an effect, not during render. React may invoke a
|
||||
// component body more than once (StrictMode double-invoke, concurrent
|
||||
// re-renders); side effects belong in useEffect.
|
||||
useEffect(() => {
|
||||
window.location.replace('/api/login');
|
||||
}, []);
|
||||
return <div aria-hidden="true" />;
|
||||
}
|
||||
|
||||
export default function App() {
|
||||
const [settingsOpen, setSettingsOpen] = useState(false);
|
||||
const phone = isPhone();
|
||||
const phone = useIsPhone();
|
||||
|
||||
// Setup status query — staleTime 0 so the wizard gate is always fresh (D-10 spirit).
|
||||
// Must be fetched before rendering any authenticated route to gate the app on /setup.
|
||||
|
||||
Reference in New Issue
Block a user