-
Notifications
You must be signed in to change notification settings - Fork 47.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Compiler Bug]: Mutating a ref passed as argument from a hook warns #29832
Comments
It feels like checking if |
@atomiks agree with your two points. It makes a lot of sense to me. |
Hi @oliviertassinari, import * as React from 'react'; export function useResizeHandle( React.useEffect(() => {
}, [newTarget]); Let me know your thoughts on this. |
I have a different use case that relies on setting the This is, as far as I can tell from reading the docs, perfectly compatible with the philosophy around refs. import React from "react";
import type { Writeable } from "zod"; // just a utility type that makes the props of an object writeable since Zod is already in my codebase
export function useMergeRefs<TRefType>(...refs: (React.LegacyRef<TRefType> | React.MutableRefObject<TRefType> | undefined)[]): React.Ref<TRefType> {
return React.useMemo(() => (value: TRefType) => {
for (const ref of refs) {
if (!ref) continue;
if (typeof ref === 'function') ref(value);
else if (typeof ref === 'string') throw new Error('Cannot merge string refs; if you are using this, you can implement this functionality yourself.');
else (ref as Writeable<typeof ref>).current = value;
}
}, [refs]);
} The error can be "fixed" by creating a no-op function, like so:import React from "react";
import type { Writeable } from "zod"; // just a utility type that makes the props of an object writeable since Zod is already in my codebase
export function useMergeRefs<TRefType>(...refs: (React.LegacyRef<TRefType> | React.MutableRefObject<TRefType> | undefined)[]): React.Ref<TRefType> {
return React.useMemo(() => (value: TRefType) => {
for (const ref_ of refs) {
const ref = noOp(ref_); // makes the React Compiler not complain
if (!ref) continue;
if (typeof ref === 'function') ref(value);
else if (typeof ref === 'string') throw new Error('Cannot merge string refs; if you are using this, you can implement this functionality yourself.');
else (ref as Writeable<typeof ref>).current = value;
}
}, [refs]);
}
function noOp<T>(value: T): T {
return value;
} |
@poteto Both examples still throw a warning in the playground preview for that PR (and, for sanity's sake, on the latest playground preview). |
The compiler's type system can not handle polymorphic types -- in your example, ref can be To make this compile, refactor the ref mutation to a helper function like this: function updateRef(ref, value) {
ref.current = value;
}
export function useMergeRefs<TRefType>(...refs: (React.LegacyRef<TRefType> | React.MutableRefObject<TRefType> | undefined)[]): React.Ref<TRefType> {
return React.useMemo(() => (value: TRefType) => {
for (const ref of refs) {
if (!ref) continue;
if (typeof ref === 'function') ref(value);
else if (typeof ref === 'string') throw new Error('Cannot merge string refs; if you are using this, you can implement this functionality yourself.');
else updateRef(ref, value);
}
}, [refs]);
} |
What kind of issue is this?
Link to repro
https://playground.react.dev/#N4Igzg9grgTgxgUxALhASwLYAcIwC4AEAVAQIZgEBKCpchAZjBBgQOQw12sDcAOgHYCEADxz4C9KPzpoI-AlDAJqYNAC8EACVL8AJgBsEACgEECeUjADmCPMiqc8AOgCyUCwCND1egHkPAFYIdAA8mgAqLgAyACJoAG4AooYYCPyEAD4E-FD6+gB8ADQCAJQEwKYEcHJghB6WBAC8DrTOisoI9GGRsQnJCKnp+UY5eSV8gvItdE7tifT0wXhGRmWN+eWVZpLSeLLyHKoa-kF0RgjxaXYELtBKiZfpBFnh0HAAFg9XZRVTZmb1GBOOCwDjpJy1ACehicAHc0Lo8O8mgReCAAIwABiwwjRE3+-ws1lswNBVwheGhCDhCKRKLRWJxeK2BAAvgIWboICDBs5SLpdF90lE0LU0ggYEZWBg7gMIJdWIUCId1AgTkslcACFhyKpLvZ6KR9Eo2eMWRw8LB5KsmhtfgSzFyeeSODLLkK8CKxfwJVKZe03QhFcqEEc1YElma-mz8WylQBtIk2PAAXSjZgtVs20d0MFIVisaH4VnseBgUAQxSmrIm7P4IFZQA
Repro steps
This seems like the same as #29196 but in reverse.
From what @josephsavona said:
This could make sense. I could see myself doing:
How often does this bug happen?
Every time
What version of React are you using?
v19
The text was updated successfully, but these errors were encountered: