You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
This repository was archived by the owner on Nov 4, 2026. It is now read-only.
Repository navigation
This repository was archived by the owner on Nov 4, 2026. It is now read-only.
plugin-form: EmbeddableForm's thank-you redirect timer is unowned too — and its default 3s window fires into "Submit Another Response" #5049
Tripped over while fixing objectui#5033 (the same defect class at the other two call sites). Filed unassigned and NOT fixed there — #5033's card names ObjectForm.tsx and WizardForm.tsx, and this is a third call site with its own config keys, so the PR for #5033 left it exactly as found.
What
packages/plugin-form/src/EmbeddableForm.tsx arms its post-submit redirect with a bare setTimeout inside the submit handler (around line 306):
Nothing stores that handle, nothing clears it, no effect owns it. Identical shape to #5033, with two differences that make it worse rather than milder:
The delay defaults to 3000ms, and the thank-you panel it renders says so out loud — Redirecting in {{seconds}} seconds… (line ~345). A multi-second pending full-page navigation is this surface's NORMAL state, not an edge authoring.
It does not even need an unmount. With config.allowMultiple, the thank-you panel offers a Submit Another Response button whose handleReset (line 327) only does setSubmitted(false); setError(null) — the pending navigation keeps ticking. So the component invites the submitter back into a fresh form and then, about three seconds later, throws the whole page away while they are typing the next response. The unmount shapes from plugin-form: the redirect delayMs timer outlives the component — a submitter who leaves during the delay is yanked back by a full-page navigation #5033 (an embed removed by the host page, a route change, a re-keyed subtree) apply on top of that.
Reachability
Live, published surface, not dormant: EmbeddableForm is exported from packages/plugin-form/src/index.tsx (line 53) and registered in the ComponentRegistry as embeddable-form (line 211), so authored metadata reaches it. It needs thankYouPage.redirectUrl to be set; redirectDelay may be left unset, which is the 3s default rather than a zero timer. Nobody loses data — the write has already succeeded before the timer is armed — so the harm is a surprising navigation (and, in the allowMultiple shape, losing what the submitter had just re-typed).
Fix shape, if this is queued
The same move #5033 took, which apps/console's FormPage took before it (PR #4992): hold the accepted destination in state, arm the wait in an effect keyed on it, clearTimeout in the cleanup. Two things this call site needs that #5033's did not:
handleReset has to clear the pending destination as well, otherwise the "submit another" path stays exactly as broken as it is today (unmount safety alone does not cover it). That is the decision worth stating in the card rather than leaving to the implementer: does Submit Another Responsecancel the declared redirect, or does the redirect win because the author declared it? Cancelling matches what the button offers.
Cheap to pin the same way #5033 was: arm the delay, unmount (or press Submit Another Response), let the clock run past the delay, assert nothing navigated — paired with a mounted case asserting the destination is still reached when the delay ends, so the pin cannot pass by having deleted the redirect.
Activity
yinlianghui commentedon Aug 17, 2026
认领(objectui 分片 PM 直辖,批次 22 补席)—— session
session_01GTRjn8xBqp75dk7kFupVRt,分支claude/issue-5049-embeddable-redirect-timer。os-dev 席位实施,PM 只读验收。同类前两处已由 PR #4992(console FormPage)与 PR #5055(#5033,ObjectForm/WizardForm,已验收入队)落地,形状已双验证:待定目的地(连同其 delay)入 state,effect 键其上,cleanup
clearTimeout。本单两个专属钉子:handleReset(Submit Another Response)取消待定 redirect —— 依据即卡面论证:按钮承诺的是「再填一份」,与三秒后丢弃整页不可共存;取消是按钮语义的机械执行,不是新口味。维护者可否决。thankYouPage.redirectUrl的 host-allow-list 契约(isRedirectUrlSafe/allowedRedirectHosts)并进 plugin-form: ObjectForm/WizardForm consume submitBehavior.url against the pre-ruling shape — out-of-contract values silently dropped, same-origin absolutes followed, mount-blind #4989/PR fix(plugin-form): consume submitBehavior.url as objectstack#7496 ruled it (#4989) #5032 的 relative-only 裁定 —— 两契约是否统一是独立问题,本单只修定时器生命周期,一行不碰 URL 判定。钉子测试按卡面:armed → unmount 与 armed → 按钮重置两条负向、mounted 到点导航一条正向(防「把功能删了换绿」)。
Generated by Claude Code
fix(plugin-form): thank-you redirect 的等待改由组件持有,unmount 与「再填一份」均取消 (ob…
fix(plugin-form): 致谢面板按组件自己的 redirect 裁定渲染,拒绝时不再假承诺跳转 (objectstack-ai…