Skip to content

[compiler] Add useFormContext to known incompatible libraries#306

Open
everettbu wants to merge 2 commits into
mainfrom
reyronald-useformcontext-incompatible-library
Open

[compiler] Add useFormContext to known incompatible libraries#306
everettbu wants to merge 2 commits into
mainfrom
reyronald-useformcontext-incompatible-library

Conversation

@everettbu

Copy link
Copy Markdown

Mirror of facebook/react#35465
Original author: reyronald


The original implementation in #34027 added useForm from react-hook-form to the known incompatible libraries list, but missed useFormContext. useFormContext returns the same API surface as useForm, including the watch() function that cannot be memoized safely.

This PR adds useFormContext with the same configuration as useForm

I repurposed @Maxou44 's original repro repo from react-hook-form/react-hook-form#11910 to demonstrate that the issue can be reproduced with useFormContext too, you can play around with the updated demo if you want to confirm, repo link below

https://github.com/reyronald/issue-react-compiler-react-hook-form

Repro details
import {
  useForm,
  useWatch,
  useFormContext,
  FormProvider,
} from "react-hook-form";

export default function App() {
  const methods = useForm();
  const { register, handleSubmit, watch, control } = methods;
  const onSubmit = (data) => console.log(data);

  const test = useWatch({ control, name: "test" });

  return (
    <div>
      <Headers description="Performant, flexible and extensible forms with easy-to-use validation." />

      <FormProvider {...methods}>
        <form onSubmit={handleSubmit(onSubmit)}>
          <input {...register("test")} placeholder="Test field" />

          <div>useForm.watch is {watch("test")}</div>

          <div>useForm.useWatch value is {test}</div>

          <Component />

          <input type="submit" />
        </form>
      </FormProvider>
    </div>
  );
}

function Component() {
  const { watch, control } = useFormContext();

  const test = useWatch({ control, name: "test" });

  return (
    <>
      <div>useFormContext.watch is {watch("test")}</div>

      <div>useForm.useWatch value is {test}</div>
    </>
  );
}
image

References

  1. issue: Watch don't work with React Compiler (React 19) react-hook-form/react-hook-form#11910
  2. #34027
  3. #34493

The original implementation in #34027 added useForm from react-hook-form
to the known incompatible libraries list, but missed useFormContext.
useFormContext returns the same API surface as useForm, including the
watch() function that cannot be memoized safely.

This PR adds useFormContext with the same configuration as useForm

I repurposed @Maxou44 's original repro repo from #11910 to demonstrate
that the issue can be reproduced with useFormContext too, you can play
around with the updated demo if you want to confirm, repo link below

https://github.com/reyronald/issue-react-compiler-react-hook-form

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Greptile Overview

Greptile Summary

This PR correctly adds useFormContext to the list of known incompatible React Hook Form APIs. The implementation mirrors the existing useForm configuration, marking only the watch() function as incompatible with memoization.

Key Changes:

  • Added useFormContext hook configuration with identical structure to useForm
  • Properly marked the watch() function with ValueKind.Mutable and knownIncompatible message
  • Used consistent configuration: Effect.Read for restParam and calleeEffect, matching the existing pattern

The change is minimal, focused, and correctly addresses the gap identified in the original implementation. Since useFormContext returns the same API surface as useForm (including the problematic watch() function), this addition is necessary for complete coverage.

Confidence Score: 5/5

  • This PR is safe to merge with no identified issues
  • The change is a straightforward addition that perfectly follows the established pattern. The configuration is identical to the existing useForm setup, correctly addresses a documented gap, and includes no logical errors or inconsistencies. The implementation is well-documented with inline comments explaining the incompatibility.
  • No files require special attention

Important Files Changed

File Analysis

Filename Score Overview
compiler/packages/babel-plugin-react-compiler/src/HIR/DefaultModuleTypeProvider.ts 5/5 Added useFormContext hook configuration identical to useForm, correctly marking the watch() function as incompatible with memoization

@greptile-apps

greptile-apps Bot commented Mar 10, 2026

Copy link
Copy Markdown

Greptile Summary

This PR adds useFormContext from react-hook-form to the React Compiler's known-incompatible libraries list, complementing the existing useForm entry added in #34027. Since useFormContext exposes the same API surface as useForm — including the memoization-unsafe watch() function — the omission was a bug that caused the compiler to silently produce incorrect memoization for components that consumed the context variant.

Changes:

  • Adds a useFormContext entry under the react-hook-form case in DefaultModuleTypeProvider.ts, with identical configuration to useForm (hook kind, watch property marked ValueKind.Mutable / knownIncompatible).
  • The knownIncompatible message is correctly scoped to useFormContext() rather than useForm().

Notes:

  • No test fixtures are added for useFormContext. The repository currently has no dedicated fixture specifically exercising useForm's incompatibility either, so this is consistent with the existing test coverage model, but adding a fixture (similar to the existing error.invalid-known-incompatible-hook-return-property pattern) would improve confidence.

Confidence Score: 5/5

  • This PR is safe to merge — it is a minimal, correctly structured addition that mirrors an existing, well-tested pattern.
  • The change is a single-entry addition to a known-incompatible registry, structurally identical to the already-merged useForm entry. The knownIncompatible message, hook kind, property shape, ValueKind.Mutable, and Effect.Read settings are all consistent with the existing entry. The motivation is clearly documented and supported by a reproducible demo. No existing logic is modified.
  • No files require special attention.

Important Files Changed

Filename Overview
compiler/packages/babel-plugin-react-compiler/src/HIR/DefaultModuleTypeProvider.ts Adds useFormContext to the react-hook-form known-incompatible block, mirroring the existing useForm entry exactly — same hook shape, same watch property marked mutable/incompatible, and a correctly updated knownIncompatible message.

Last reviewed commit: c0951ba

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants