-
-
Notifications
You must be signed in to change notification settings - Fork 495
Fix #1050: useField returns undefined on initial render (v7.0.0 regression) #1058
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 8 commits
138dd5a
03ec690
dcf1964
b114fd1
6631137
31bc98b
69c3fbb
ac12635
6a763c7
e7eee71
e3837b5
76616e6
19cbe2c
c8e8fbc
d8e1a56
b27453b
759d95c
d7a8d90
5bc2c21
e08e6ea
31ad254
a708212
c52d897
2e9a798
3cffe3e
01e23c5
aceb1b8
b4c1801
093a2f0
0061dd8
ef48a8d
6d0f2eb
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -97,54 +97,30 @@ function useField< | |
|
|
||
| // Initialize state with proper field state from Final Form without callbacks | ||
| const [state, setState] = React.useState<FieldState<any>>(() => { | ||
| // Get the current field state from Final Form without registering callbacks | ||
| const existingFieldState = form.getFieldState(name as keyof FormValues); | ||
| // FIX #1050: Register field synchronously to get proper initial state | ||
| // This is the same approach used in v6.5.9 to ensure Form initialValues | ||
| // are available on first render. | ||
| let initialFieldState: FieldState<any> = {} as FieldState<any>; | ||
|
|
||
| if (existingFieldState) { | ||
| // If allowNull is true and the initial value was null, preserve it | ||
| // (and its formatted version is not null, meaning it was formatted away) | ||
| if (allowNull && existingFieldState.initial === null && existingFieldState.value !== null) { | ||
| return { | ||
| ...existingFieldState, | ||
| value: null, // Force value back to null | ||
| initial: null, // Ensure our local state's 'initial' also reflects this | ||
| }; | ||
| } | ||
| return existingFieldState; | ||
| } | ||
| // Temporarily disable destroyOnUnregister | ||
| const destroyOnUnregister = form.destroyOnUnregister; | ||
| form.destroyOnUnregister = false; | ||
|
|
||
| // If no existing state, create a proper initial state | ||
| let initialStateValue = initialValue; | ||
| if (component === "select" && multiple && initialValue === undefined) { | ||
| initialStateValue = []; | ||
| } | ||
| // Pause validation to prevent notifications during synchronous registration | ||
| form.pauseValidation(); | ||
|
|
||
| // Register field synchronously with silent=true, capture state, then unregister | ||
| register((fieldState) => { | ||
| initialFieldState = fieldState; | ||
| }, true)(); | ||
|
|
||
| // Resume validation | ||
| form.resumeValidation(); | ||
|
|
||
| // Restore destroyOnUnregister to its original value | ||
| form.destroyOnUnregister = destroyOnUnregister; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: cat -n src/useField.ts | head -150Repository: final-form/react-final-form Length of output: 5731 🏁 Script executed: # Check if final-form is installed and look at its type definitions
fd -e d.ts -e ts node_modules/final-form 2>/dev/null | head -20Repository: final-form/react-final-form Length of output: 53 🏁 Script executed: # Search for error handling patterns in the codebase
rg "try.*finally" src/ -A 2 -B 2Repository: final-form/react-final-form Length of output: 53 🏁 Script executed: # Search for registerField usage patterns
rg "registerField" src/ -B 3 -A 3Repository: final-form/react-final-form Length of output: 1337 🏁 Script executed: # Check package.json for final-form version
cat package.json | grep -A 2 -B 2 "final-form"Repository: final-form/react-final-form Length of output: 1486 🏁 Script executed: # Look for pauseValidation and resumeValidation usage in the codebase
rg "pauseValidation|resumeValidation" src/Repository: final-form/react-final-form Length of output: 414 🏁 Script executed: # Check if there are any error boundaries or error handling in the initialization
rg "try\s*\{|catch\s*\(" src/ -B 2 -A 5Repository: final-form/react-final-form Length of output: 53 🏁 Script executed: # Check the types to understand registerField behavior
fd -e d.ts node_modules/final-form/ 2>/dev/null | xargs grep -l "registerField" 2>/dev/nullRepository: final-form/react-final-form Length of output: 55 🏁 Script executed: # Read ReactFinalForm.tsx to see the context around pauseValidation/resumeValidation
rg "pauseValidation|resumeValidation" src/ReactFinalForm.tsx -B 5 -A 5Repository: final-form/react-final-form Length of output: 1423 🏁 Script executed: # Check if final-form types exist in node_modules
cat node_modules/final-form/package.json 2>/dev/null | grep -A 1 "typings\|types"Repository: final-form/react-final-form Length of output: 474 🏁 Script executed: # Try to find and read the final-form types
cat node_modules/final-form/index.d.ts 2>/dev/null | grep -A 10 "pauseValidation\|registerField" | head -50Repository: final-form/react-final-form Length of output: 53 🏁 Script executed: # Search for registerField in final-form types more directly
find node_modules/final-form -name "*.d.ts" -o -name "*.ts" 2>/dev/null | head -10Repository: final-form/react-final-form Length of output: 563 🏁 Script executed: # Try to view final-form's index.d.ts
head -200 node_modules/final-form/index.d.ts 2>/dev/null | tail -100Repository: final-form/react-final-form Length of output: 53 🏁 Script executed: # Search for any validation-related code in test files that might show error scenarios
rg "registerField.*throw|throw.*registerField|pauseValidation.*error" src/Repository: final-form/react-final-form Length of output: 53 🏁 Script executed: # Read the final-form FinalForm.d.ts to understand registerField
cat node_modules/final-form/dist/FinalForm.d.ts 2>/dev/null | grep -A 20 "registerField"Repository: final-form/react-final-form Length of output: 53 🏁 Script executed: # Also check the index.d.ts for FormApi
cat node_modules/final-form/dist/index.d.ts 2>/dev/null | grep -A 15 "registerField"Repository: final-form/react-final-form Length of output: 53 🏁 Script executed: # Look for the actual implementation in final-form
cat node_modules/final-form/dist/FinalForm.js 2>/dev/null | grep -A 30 "registerField\s*=" | head -40Repository: final-form/react-final-form Length of output: 53 🏁 Script executed: # Check if final-form package is actually in node_modules
ls -la node_modules/final-form/ 2>/dev/null | head -20Repository: final-form/react-final-form Length of output: 432 🏁 Script executed: # Look for test files that might exercise registerField behavior
rg "registerField" src/*.test.* -B 3 -A 3Repository: final-form/react-final-form Length of output: 907 🏁 Script executed: # Search for any issue references or comments about error handling in state initialization
rg "FIX `#1050`|try.*finally|error.*register|throw" src/useField.tsRepository: final-form/react-final-form Length of output: 145 🏁 Script executed: # Search for issue `#1050` or related context
rg "1050" . --type ts --type tsx --type jsRepository: final-form/react-final-form Length of output: 98 🏁 Script executed: # Look at git history or comments around this code
git log --all --oneline --grep="1050" 2>/dev/null | head -10Repository: final-form/react-final-form Length of output: 133 🏁 Script executed: # Check if there are any error handling tests for useField
rg "useField.*error|useField.*throw" src/*.test.* -B 2 -A 5Repository: final-form/react-final-form Length of output: 53 🏁 Script executed: # Look at the full context of the useState initializer
sed -n '98,125p' src/useField.tsRepository: final-form/react-final-form Length of output: 1104 🏁 Script executed: # Check the final-form dist code for registerField implementation
cat node_modules/final-form/dist/FinalForm.js 2>/dev/null | sed -n '1,100p'Repository: final-form/react-final-form Length of output: 3564 🏁 Script executed: # Search for registerField in the final-form dist
grep -n "registerField" node_modules/final-form/dist/FinalForm.js 2>/dev/null | head -5Repository: final-form/react-final-form Length of output: 399 🏁 Script executed: # Get the registerField implementation
grep -A 50 "function registerField\|registerField\s*=\s*function" node_modules/final-form/dist/FinalForm.js 2>/dev/null | head -60Repository: final-form/react-final-form Length of output: 53 🏁 Script executed: # Check the git commit that added this fix
git show ac12635 --stat 2>/dev/null | head -20Repository: final-form/react-final-form Length of output: 1105 🏁 Script executed: # Get the full registerField implementation from final-form
sed -n '627,700p' node_modules/final-form/dist/FinalForm.js 2>/dev/nullRepository: final-form/react-final-form Length of output: 3937 🏁 Script executed: # Check what happens if an exception occurs in a useState initializer
# Look for any tests or documentation about error handling
rg "useState.*throw|initializer.*error" src/Repository: final-form/react-final-form Length of output: 53 🏁 Script executed: # Look for the complete register function and its behavior
sed -n '57,96p' src/useField.tsRepository: final-form/react-final-form Length of output: 1401 🏁 Script executed: # Check if validators can throw exceptions
rg "validate\(" src/useField.ts -B 3 -A 3Repository: final-form/react-final-form Length of output: 53 🏁 Script executed: # Look for try/catch patterns around register/validator calls in tests
rg "register.*throw|validator.*throw|try.*register" src/*.test.*Repository: final-form/react-final-form Length of output: 53 🏁 Script executed: # Check the beforeSubmit implementation for potential errors
sed -n '68,88p' src/useField.tsRepository: final-form/react-final-form Length of output: 649 🏁 Script executed: # Search for any documentation or comments about error scenarios
rg "registerField.*error|throw|exception" . --type js --type ts -g '!node_modules'Repository: final-form/react-final-form Length of output: 938 🏁 Script executed: # Check if there are any issues or PRs about error handling in this code path
git log --all --oneline -- src/useField.ts 2>/dev/null | head -20Repository: final-form/react-final-form Length of output: 171 🏁 Script executed: # Check for any test files that test error scenarios with validators
find src -name "*.test.*" -exec grep -l "validator.*throw\|beforeSubmit.*throw" {} \;Repository: final-form/react-final-form Length of output: 53 🏁 Script executed: # Verify the current state - does the code have try/finally?
grep -A 20 "pauseValidation" src/useField.ts | grep -E "try|finally"Repository: final-form/react-final-form Length of output: 53 Guarantee cleanup of validation pause and destroyOnUnregister. 🛡️ Suggested fix // Temporarily disable destroyOnUnregister
const destroyOnUnregister = form.destroyOnUnregister;
form.destroyOnUnregister = false;
// Pause validation to prevent notifications during synchronous registration
- form.pauseValidation();
-
- // Register field synchronously with silent=true, capture state, then unregister
- register((fieldState) => {
- initialFieldState = fieldState;
- }, true)();
-
- // Resume validation
- form.resumeValidation();
-
- // Restore destroyOnUnregister to its original value
- form.destroyOnUnregister = destroyOnUnregister;
+ form.pauseValidation();
+ try {
+ // Register field synchronously with silent=true, capture state, then unregister
+ register((fieldState) => {
+ initialFieldState = fieldState;
+ }, true)();
+ } finally {
+ // Resume validation and restore destroyOnUnregister
+ form.resumeValidation();
+ form.destroyOnUnregister = destroyOnUnregister;
+ }🤖 Prompt for AI Agents |
||
|
|
||
| return { | ||
| active: false, | ||
| blur: () => { }, | ||
| change: () => { }, | ||
| data: data || {}, | ||
| dirty: false, | ||
| dirtySinceLastSubmit: false, | ||
| error: undefined, | ||
| focus: () => { }, | ||
| initial: initialStateValue, | ||
| invalid: false, | ||
| length: undefined, | ||
| modified: false, | ||
| modifiedSinceLastSubmit: false, | ||
| name, | ||
| pristine: true, | ||
| submitError: undefined, | ||
| submitFailed: false, | ||
| submitSucceeded: false, | ||
| submitting: false, | ||
| touched: false, | ||
| valid: true, | ||
| validating: false, | ||
| value: initialStateValue, | ||
| visited: false, | ||
| }; | ||
| return initialFieldState; | ||
| }); | ||
|
|
||
|
coderabbitai[bot] marked this conversation as resolved.
|
||
| React.useEffect(() => { | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.