Skip to content

useFieldContext reactivity broken by React Compiler and ternary operator #1832

@JamesHyot

Description

@JamesHyot

Describe the bug

When using useFieldContext with React Compiler and a ternary expression to render or not an input, the reactivity of the field breaks and its values is not updated when typing.

This is caused by the Compiler changing the dependency for a rerender from "field.state.value" to "field", which is always the same object so no UI update is made.
I have no idea if this is really an issue with @tanstack/form or the React Compiler itself, though I can get why the compiler would want to memo based on "field" and not only its subproperties.

This example doesn't work (and neither does a {canBeExtended && (<input value={field.state.value} onChange={(e) => field.handleChange(e.target.value)} />)} :

import { useFieldContext } from './form-context.tsx'

export function TextField({ label, canBeExtended }: { label: string, canBeExtended: boolean }) {
  // The `Field` infers that it should have a `value` type of `string`
  const field = useFieldContext<string>()
  return (
    <label>
      <span>{label}</span>
			{canBeExtended ?
				(<input
					value={field.state.value}
					onChange={(e) => field.handleChange(e.target.value)}
					/>)
				: (<div className='extended'>
					<input
						value={field.state.value}
						onChange={(e) => field.handleChange(e.target.value)}
					/>
				</div>)}
    </label>
  )
}

See the Compiler playground which outputs an if ($[2] !== canBeExtended || $[3] !== field) { which is different from the if ($[4] !== field.state.value || $[5] !== t2) { of this basic playground

There are several workarounds available to us, destructuring field, writing the ternary expression another way, or using a temp variable : "const val = field.state.value". However this issue caught me off-guard so I decided to submit it.

Your minimal, reproducible example

https://playground.react.dev/#N4Igzg9grgTgxgUxALhASwLYAcIwC4AEwBUYCAYmggDYAmAwhAHZ4IAehAvgQGYwQYCAcgB0Aeh64MAWjjNWHEXjBshAHSYb2OfLyhM4eNMwIAVdnko1aACmLUAhgCMaAGgJwHTAEIIAohwITLQItAScyEQEji7UkWB4MGhMAObunj7+gcGhkU4QENQIXuEAlEQaBARiYmYAFggEAAZWdE0EyTwIMGAEeHUOhGiEYHXQdAQDAG6NDs1TDtRQCO14AJ5YjRA8zQlJqU2VHswJvFQTALwkZK0M8hYAPHvJKQB8NqVHMAh4sEwENiOVQeMRoryBVQITywXlewFB1E4DzEYBhTHBmjwaixeGAGV8AVYOTCAH4NNiKTibA9klgoFjMZTKQslggLsAeOdaCIEoMECIWctOOScUy8Mx6ANUmzgDYEOULq8ztYRFLaEVJV4Ugg5UoHDBtXgBYtlqVhYzRTixK9PhbKZFqbQ0FMPI4wGAAHIODBsoQWIIhWhCDFiyk0ph0hmhy2CmWclW81jG1nm6OUiVS7XsuUKpXxuiqrzqhCa6W6vD6w3J02py2U60isXIp1TG3myFQsQIjFVW2cECuEByJiclIodDYXCEdabKIABSWKWSAHksEYTuFePxBEInM4aNIsIvktJvg5DLIBFg0EUYGInQkhABuclMOxHGpybA3wbGJgAWQgEJIjUEBFmoUCNG4MBfzAeNegXKAlyYVd1yYMBSifAdwDGAB3ABJFhuiYRYwBQHhSIQTggA

Steps to reproduce

Create a pre-bound field component which renders an input conditionnally
Add React Compiler
The field doesn't update :(

Expected behavior

The input should update when you type something in it

How often does this bug happen?

None

Screenshots or Videos

No response

Platform

Not OS or Browser specific

TanStack Form adapter

react-form

TanStack Form version

1.19.1

TypeScript version

5.9.2

Additional context

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions