mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-07-26 09:52:11 +03:00
fix(translator): suppress react-hooks/set-state-in-effect in deep-link sync useEffects (follow-up GAP-NOVO-4/5)
The useRef-based pattern is required so that a manual user close while forceOpen stays true does not immediately re-open the accordion on the next render (see test 'toggle closes accordion again'). The setState calls inside the false→true guard are an intentional sync of an external deep-link prop into local component state — a valid use case the react-hooks/set-state-in-effect heuristic does not recognize, so suppress it with an inline comment explaining the rationale. Clarified the comment on the prevForceOpen useRef to point at the regression it prevents.
This commit is contained in:
@@ -216,16 +216,17 @@ export default function CompressionPreviewAccordion({
|
||||
// Lazy-render guard (D7): track whether the accordion has ever been opened.
|
||||
const [hasOpened, setHasOpened] = useState(forceOpen);
|
||||
const [open, setOpen] = useState(forceOpen);
|
||||
// Track previous forceOpen value to detect false→true transitions only.
|
||||
// Track previous forceOpen so the effect only reacts to false→true transitions.
|
||||
// Without this, a manual close while forceOpen stays true would re-open the accordion
|
||||
// on the very next render (the test "toggle closes accordion again" guards this).
|
||||
const prevForceOpen = useRef(forceOpen);
|
||||
|
||||
// Sync forceOpen changes from parent after mount (deep-link / back-forward navigation).
|
||||
// Only reacts to a false→true transition so a manual close is not overridden while
|
||||
// forceOpen remains true (e.g. user toggles closed after a deep-link open).
|
||||
useEffect(() => {
|
||||
const prev = prevForceOpen.current;
|
||||
prevForceOpen.current = Boolean(forceOpen);
|
||||
if (!prev && forceOpen) {
|
||||
// eslint-disable-next-line react-hooks/set-state-in-effect -- syncing deep-link prop into local state
|
||||
setOpen(true);
|
||||
setHasOpened(true);
|
||||
onOpenChange?.(true);
|
||||
|
||||
@@ -140,16 +140,17 @@ export default function StreamTransformerAccordion({
|
||||
const [open, setOpen] = useState(Boolean(forceOpen));
|
||||
// D7 lazy-render guard: once mounted, keep content in DOM.
|
||||
const [hasOpened, setHasOpened] = useState(Boolean(forceOpen));
|
||||
// Track previous forceOpen value to detect false→true transitions only.
|
||||
// Track previous forceOpen so the effect only reacts to false→true transitions.
|
||||
// Without this, a manual close while forceOpen stays true would re-open the accordion
|
||||
// on the very next render.
|
||||
const prevForceOpen = useRef(Boolean(forceOpen));
|
||||
|
||||
// Sync forceOpen changes from parent after mount (deep-link / back-forward navigation).
|
||||
// Only reacts to a false→true transition so a manual close is not overridden while
|
||||
// forceOpen remains true (e.g. user toggles closed after a deep-link open).
|
||||
useEffect(() => {
|
||||
const prev = prevForceOpen.current;
|
||||
prevForceOpen.current = Boolean(forceOpen);
|
||||
if (!prev && forceOpen) {
|
||||
// eslint-disable-next-line react-hooks/set-state-in-effect -- syncing deep-link prop into local state
|
||||
setOpen(true);
|
||||
setHasOpened(true);
|
||||
onOpenChange?.(true);
|
||||
|
||||
Reference in New Issue
Block a user