fix(design): avoid stack overflow on cyclic Form field values - #1576
Merged
Merged
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
dengfuping
force-pushed
the
fix/form-revalidate-cyclic-values
branch
from
September 10, 2026 09:23
b809e49 to
9277325
Compare
This branch was successfully deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

📦 Modified package
🤔 This is a ...
🔗 Related issue link
N/A
💡 Background and solution
With the default
validateMode="onSubmit"+reValidateMode="onChange",Forminjected a revalidation step intoonValuesChange. To know which fields had changed, it recursively walked the changed values (getChangedNamePaths), a walk with no cycle detection:Changed values are often non-plain in practice — e.g. a
labelInValueSelectwhoselabelis a React node, and a React element's_ownerpoints back into the fiber graph. Every field change then threw before the consumer's ownonValuesChangeran. The walk also ran on every change even when its result was discarded (before the first submit, only fields that already show errors get revalidated).Solution
onFieldsChange(changedFields[].name) instead of re-deriving them from values, so the consumer'sonValuesChangeis passed through untouched. A field counts as changed only when its value differs from the last value seen for it (identity comparison, mirroring rc-field-form's ownnewValue !== valuedetection), which also filters out the validation-state updates thatchangedFieldscarries.resetFields()so a full reset clears everything while a partialresetFields(['name'])re-seeds that field. This keeps the reset semantics (submittedcleared on full reset only) when the sameForm.useForm()instance is reused across aFormunmount / remount.onTouchednow marks a field as touched on blur instead of on the first change: a change reportstouched: truewithout validating, sotouchedcannot tell typing apart from blur. Fields without rules are unaffected as they have nothing to validate.validateModedemo declares its mode union locally instead of importing the type from the package root, so the package root keeps exporting onlyFormProps/FormItemPropsforForm.📝 Changelog
- 🐞 Fixed the injected revalidation throwing
RangeError: Maximum call stack size exceededwhen a changed value contains a circular reference, such as alabelInValueSelectwhose label is a React node.- 🐞
onValuesChangeis no longer wrapped, so the consumer callback always runs when the injected revalidation is active.- 🐞 Fixed
resetFields()not clearing the submitted state: after a full reset the field counts as untouched and does not revalidate on change, including when theFormunmounts and remounts with the sameForm.useForm()instance.- 🐞 修复注入的校验在变更值包含循环引用时抛出
RangeError: Maximum call stack size exceeded的问题,例如labelInValue的Select以 React 节点作为 label。- 🐞 不再包装
onValuesChange,注入校验生效时用户回调也会正常执行。- 🐞 修复
resetFields()未重置提交状态的问题:完整重置后字段视为未触碰,变更时不再触发校验;Form 卸载后使用同一Form.useForm()实例重新挂载时同样成立。☑️ Self-Check before Merge