form icon indicating copy to clipboard operation
form copied to clipboard

HMR problem in Vite with `useFieldContext()`

Open fullheart opened this issue 8 months ago • 4 comments

Describe the bug

After modifying a component that uses the useFieldContext hook, I get the following error in the web console after Vite has hot-reloaded the component:

Error: `fieldContext` only works when within a `fieldComponent` passed to `createFormHook`
    at useFieldContext (@tanstack_react-form.js?v=fd612f6a:2205:13)
    at TextField (TextField.tsx?t=1743182881241:24:17)
    at react-stack-bottom-frame (react-dom_client.js?v=fd612f6a:16192:20)
    at renderWithHooks (react-dom_client.js?v=fd612f6a:4306:24)
    at updateFunctionComponent (react-dom_client.js?v=fd612f6a:5972:21)
    at beginWork (react-dom_client.js?v=fd612f6a:7048:20)
    at runWithFiberInDEV (react-dom_client.js?v=fd612f6a:726:18)
    at performUnitOfWork (react-dom_client.js?v=fd612f6a:10831:98)
    at workLoopSync (react-dom_client.js?v=fd612f6a:10692:43)
    at renderRootSync (react-dom_client.js?v=fd612f6a:10675:13)

Your minimal, reproducible example

https://stackblitz.com/edit/vitejs-vite-rg13w71d?file=src%2Fcomponents%2FFieldWrapper.tsx

Steps to reproduce

  1. Open Stackblitz link (see above)
  2. Open preview in new tab, open inspector and switch to "Console"
  3. Go back to Stackblitz and add a class in the src/components/FieldWrapper.tsx and save the file
  4. Go back to preview, now the page is blank an you see an error in the console

Expected behavior

Vite reload components and show the changed component.

How often does this bug happen?

Every time

Screenshots or Videos

No response

Platform

  • OS: macOS
  • Browser: Chrome
  • Version: 143

TanStack Form adapter

react-form

TanStack Form version

v1.2.0

TypeScript version

v5.7.2

Additional context

No response

fullheart avatar Mar 28 '25 17:03 fullheart

The same thing happens if you use "useFormContext".

However, this only happens when I use the recommended pattern of exposing the components via createFormHook(). If I don't provide them to createFormHook, I can use them (via <ComponentName> instead of <form.ComponentName> or <field.ComponentName>) and HMR works fine too.

MGRatEJOT avatar Apr 01 '25 04:04 MGRatEJOT

I managed to fix this by having two files. The reload will probably trigger the context to rerender because of HMR.

File A ( context file):

import { createFormHookContexts } from '@tanstack/react-form'

export const { fieldContext, formContext, useFieldContext, useFormContext } =
  createFormHookContexts()

File B (hook file):

import { fieldContext, formContext } from './form-context'

export const { useAppForm } = createFormHook({
  fieldContext,
  formContext,
  fieldComponents: {
... your field components
},
formComponents{
.... your form components
}

zwaardje avatar Apr 29 '25 08:04 zwaardje

I managed to fix this by having two files. The reload will probably trigger the context to rerender because of HMR.

File A ( context file):

import { createFormHookContexts } from '@tanstack/react-form'

export const { fieldContext, formContext, useFieldContext, useFormContext } =
  createFormHookContexts()

File B (hook file):

import { fieldContext, formContext } from './form-context'

export const { useAppForm } = createFormHook({
  fieldContext,
  formContext,
  fieldComponents: {
... your field components
},
formComponents{
.... your form components
}

Works great, thanks. It even works if I re-export both files through an index file.

MGRatEJOT avatar Apr 29 '25 08:04 MGRatEJOT

I managed to fix this by having two files. The reload will probably trigger the context to rerender because of HMR.

File A ( context file):

import { createFormHookContexts } from '@tanstack/react-form'

export const { fieldContext, formContext, useFieldContext, useFormContext } =
  createFormHookContexts()

File B (hook file):

import { fieldContext, formContext } from './form-context'

export const { useAppForm } = createFormHook({
  fieldContext,
  formContext,
  fieldComponents: {
... your field components
},
formComponents{
.... your form components
}

Thank you! This fixed it for me. I couldn't figure out why it kept on happening.

amaify avatar May 29 '25 11:05 amaify

Still not working for me after doing just that sadly...

lazharichir avatar Jul 28 '25 21:07 lazharichir

Solid timing!

#1641 plans to fix it, but I'll need confirmation that it actually does. Especially from you @lazharichir since you said resolving the circular dependency didn't fix it.

I gave the provided reproducible example a try and it appears to work? Either way, this is quite a small fix, which makes me suspicious that it's not the end of that story. Feedback is appreciated!

Commands to install the PR version:

https://github.com/TanStack/form/pull/1641#issuecomment-3130777297

LeCarbonator avatar Jul 29 '25 05:07 LeCarbonator

It's perfectly fine to extract useAppForm into a separate file. Of course, after you modify and save that file, you will still encounter the same error.

LiMao00 avatar Aug 07 '25 06:08 LiMao00