Skip to content
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

fix(core, react-form): Avoid set state error in React by avoiding set… #1250

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

juanvilladev
Copy link
Contributor

@juanvilladev juanvilladev commented Mar 8, 2025

…ting default value until mount #1134

Due to the FieldApi constructor setting defaultValue in the constructor we violate: https://react.dev/link/setstate-in-render

UPDATE: We're going with option 2 below: moving set default value to mount function.

To avoid this I added a new flag which will prevent setting the default value within the constructor:

  /**
   * If true, the default value will not be set in the constructor.
   */
  deferDefaultValue?: boolean

Within the react react-form package, we then set that flag true and do the following

  const [fieldApi] = useState(() => {
    const api = new FieldApi({
      ...opts,
      form: opts.form,
      name: opts.name,
      deferDefaultValue: true, // Prevents https://react.dev/link/setstate-in-render by setting the default value after initial mount for React
    })

  //...
  useIsomorphicLayoutEffect(() => {
    if (fieldApi.options.defaultValue !== undefined) {
      fieldApi.form.setFieldValue(
        fieldApi.name,
        fieldApi.options.defaultValue as never,
        {
          dontUpdateMeta: true,
        },
      )
    }
  }, [fieldApi])

Please let me know if you prefer this implementation ^^

Or a different implementation where we can simply move the following code into the mount function of the FieldApi class:

if (opts.defaultValue !== undefined) {
this.form.setFieldValue(this.name, opts.defaultValue as never, {
dontUpdateMeta: true,
})
}

This also solves the problem, though now we'd be affecting all other packages not just the React one. Tests pass for either implementation!

Thanks in advance!

Copy link

nx-cloud bot commented Mar 8, 2025

View your CI Pipeline Execution ↗ for commit f4f1055.

Command Status Duration Result
nx affected --targets=test:sherif,test:knip,tes... ✅ Succeeded 1m 59s View ↗
nx run-many --target=build --exclude=examples/** ✅ Succeeded 23s View ↗

☁️ Nx Cloud last updated this comment at 2025-03-12 01:39:16 UTC

Copy link

pkg-pr-new bot commented Mar 8, 2025

Copy link

codecov bot commented Mar 8, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 88.81%. Comparing base (4ef7fd1) to head (f4f1055).
Report is 1 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #1250   +/-   ##
=======================================
  Coverage   88.81%   88.81%           
=======================================
  Files          28       28           
  Lines        1269     1269           
  Branches      331      331           
=======================================
  Hits         1127     1127           
  Misses        127      127           
  Partials       15       15           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Member

@crutchcorn crutchcorn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I'd rather add the defaultValue setting inside of mount.

Also, ideally we don't have to set this flag to do that. If we set it inside of mount, do all tests still pass on all adapters?

@juanvilladev juanvilladev force-pushed the fix/1134_default_value_react_error branch from cc55fba to e04526a Compare March 12, 2025 01:24
@@ -1519,7 +1520,6 @@ export class FieldApi<

// TODO: Dedupe this logic to reduce bundle size
for (const validateObj of validates) {
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line is not needed, ESLint removes on save

@juanvilladev
Copy link
Contributor Author

I think I'd rather add the defaultValue setting inside of mount.

Also, ideally we don't have to set this flag to do that. If we set it inside of mount, do all tests still pass on all adapters?

All tests passing on adapters, moved to simpler version of setting field value on mount function. Kept test within React that specifically tests the issue.

@juanvilladev juanvilladev requested a review from crutchcorn March 12, 2025 01:26
… react set state on render error + include test in react package
@juanvilladev juanvilladev force-pushed the fix/1134_default_value_react_error branch from e04526a to 5c4450e Compare March 12, 2025 01:34
@juanvilladev
Copy link
Contributor Author

I think I'd rather add the defaultValue setting inside of mount.

Also, ideally we don't have to set this flag to do that. If we set it inside of mount, do all tests still pass on all adapters?

Updated!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants