Closed erikshestopal closed 2 weeks ago
Thanks for filing this. If i'm understanding correctly, the issue is with the following two lines:
const form = useForm({ defaultValues: { customerId: "", addressId: "" } });
const customerId = form.watch("customerId");
Where the customerId
isn't updating when React Compiler is applied.
React Compiler is applying the equivalent of the following to this code:
const form = useForm({ defaultValues: { customerId: "", addressId: "" } });
const customerId = useMemo(() => form.watch("customerId"), [form]);
If you do the same, and apply useMemo (without the compiler), does customerId
update as you'd expect? Note that React components must be pure/idempotent. If props, state, and context haven't changed, then the component is expected to return the same result. Since form
is the same, it's expected that customerId
would be the same too. So it would help to understand if customerId updates if you use the useMemo version without compiler applied.
@josephsavona Thanks for the quick response.
If you do the same, and apply useMemo (without the compiler), does customerId update as you'd expect?
const form = useForm({ defaultValues: { customerId: "", addressId: "" } }); const customerId = useMemo(() => form.watch("customerId"), [form]);
If I apply this change manually without the compiler enabled, I still get the same result (customerId
not being updated) because as you mentioned, form
remains the same across re-renders.
I can get around issue using the useWatch
hook react-hook-form
provides but it was unexpected that the behavior changed with the compiler enabled.
Thanks for confirming. As I noted above, React expects components to be idempotent and only update if their props, state, or context changes. It looks like the watch()
API isn't using state to tell React that something has changed, which goes against React's rules around idempotency.
The useWatch()
API looks like it does use internal state to tell React when changes occur, so that should work just fine (both with useMemo and React Compiler).
Got it - thanks! Will close out then since this works as expected when using useWatch
.
What kind of issue is this?
Link to repro
https://github.com/erikshestopal/react-compiler-bug
Repro steps
Reproduction steps:
bun install
bun dev
to start the dev serverWhen trying to read a value during render using
react-hook-form
's.watch
API with thebabel-plugin-react-compiler
plugin enabled, the value is not updated and the component that is supposed to be rendered conditionally never renders.How often does this bug happen?
Every time
What version of React are you using?
19.0.0-rc-3f1436cca1-20240516