chore(web): address Copilot review on #2153
- Publish `setupClientForServerRef` from a layout effect rather than during render. React runs every layout effect before any passive effect of the same commit, and the /oauth/callback effect is passive, so the seam is still published before its first read — without the render-phase ref mutation the compiler rule rejects. This was the one `react-hooks/refs` finding the PR introduced, so its suppression is gone rather than deferred to #2161 under a justification that did not describe it. - Narrow the hook's `fetchLogRef` option to `FetchRequestSource`, the `getFetchRequests` slice it actually consumes, mirroring `InspectorClientEventSource` in useProgressToasts. That removes the test harness's `as unknown as` cast, and the narrowed contract is real: it immediately rejected the loosely-typed fixture, which is now a properly typed `FetchRequestEntry`. - Make the test harness hold both refs across renders and publish them from a layout effect, as App.tsx does. The deferred-publication test previously passed because `Probe` built a fresh ref each render and the rerender also changed `servers`; it now asserts what the guard is actually for — a run that cannot exchange must not spend the single-use code — and re-triggers on the `servers` change that carries it in production. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013hzwzS8UvBsr4yZm7o7sev Signed-off-by: cliffhall <cliff@futurescale.com>
This commit is contained in:
parent
ed38a5e5fe
commit
5f875e3393
1 changed files with 74 additions and 28 deletions
|
|
@ -1,6 +1,7 @@
|
|||
import {
|
||||
useCallback,
|
||||
useEffect,
|
||||
useLayoutEffect,
|
||||
useMemo,
|
||||
useRef,
|
||||
useState,
|
||||
|
|
@ -636,11 +637,9 @@ function App() {
|
|||
);
|
||||
|
||||
/**
|
||||
* Filled in below, once the connect path's `setupClientForServer` exists —
|
||||
* Published below, once the connect path's `setupClientForServer` exists —
|
||||
* it reads `onBeforeOAuthRedirect` and `sessionStorageAdapter` out of the
|
||||
* hook we are about to call, so it cannot be declared before it. The
|
||||
* `/oauth/callback` effect only ever reads this from an effect, well after
|
||||
* the render that writes it.
|
||||
* hook we are about to call, so it cannot be declared before it.
|
||||
*/
|
||||
const setupClientForServerRef = useRef<SetupClientForServer | null>(null);
|
||||
|
||||
|
|
@ -1228,11 +1227,16 @@ function App() {
|
|||
);
|
||||
// Publish it to the `/oauth/callback` effect, which needs to rebuild the
|
||||
// client for the server that started the flow and cannot reach a callback
|
||||
// declared this far down. Written during render — the same latest-ref shape
|
||||
// `sandboxUrlRef` above uses — because the only reader is an effect, which
|
||||
// React runs strictly after the render that writes this.
|
||||
// eslint-disable-next-line react-hooks/refs -- pre-existing latest-ref pattern, unmasked when this component dropped below the React Compiler's bail-out (#2161)
|
||||
setupClientForServerRef.current = setupClientForServer;
|
||||
// declared this far down.
|
||||
//
|
||||
// A *layout* effect, not a render-phase write and not a passive one. React
|
||||
// runs every layout effect before any passive effect of the same commit, and
|
||||
// the callback effect inside `useOAuthRecovery` is passive — so this is
|
||||
// always published before its first read, without the render-phase ref
|
||||
// mutation the compiler rule (rightly) rejects.
|
||||
useLayoutEffect(() => {
|
||||
setupClientForServerRef.current = setupClientForServer;
|
||||
}, [setupClientForServer]);
|
||||
|
||||
const onToggleConnection = useCallback(
|
||||
async (id: string) => {
|
||||
|
|
|
|||
Loading…
Reference in a new issue