form icon indicating copy to clipboard operation
form copied to clipboard

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

Open juanvilladev opened this issue 11 months ago • 5 comments

…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: https://github.com/TanStack/form/blob/135b88686bf9d10115828cd852ef2bd1201f5776/packages/form-core/src/FieldApi.ts#L999-L1003

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!

juanvilladev avatar Mar 08 '25 02:03 juanvilladev

View your CI Pipeline Execution ↗ for commit 6b912195a0be05f652d2d4fc3084a2e0087aef6b.

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

☁️ Nx Cloud last updated this comment at 2025-03-20 11:20:52 UTC

nx-cloud[bot] avatar Mar 08 '25 02:03 nx-cloud[bot]

Codecov Report

All modified and coverable lines are covered by tests :white_check_mark:

Project coverage is 88.86%. Comparing base (caf2837) to head (6b91219). Report is 2 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #1250   +/-   ##
=======================================
  Coverage   88.86%   88.86%           
=======================================
  Files          28       28           
  Lines        1275     1275           
  Branches      332      332           
=======================================
  Hits         1133     1133           
  Misses        127      127           
  Partials       15       15           

:umbrella: View full report in Codecov by Sentry.
:loudspeaker: 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.

codecov[bot] avatar Mar 08 '25 02:03 codecov[bot]

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 avatar Mar 12 '25 01:03 juanvilladev

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!

juanvilladev avatar Mar 12 '25 01:03 juanvilladev

LGTM 🚀

Just had to fix the conflict🤟

harry-whorlow avatar Mar 20 '25 11:03 harry-whorlow