Skip to content
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

useRef returns T or undefined, but NodeProps.ref only returns T #3124

Open
arswaw opened this issue Dec 20, 2023 Discussed in #3121 · 4 comments
Open

useRef returns T or undefined, but NodeProps.ref only returns T #3124

arswaw opened this issue Dec 20, 2023 Discussed in #3121 · 4 comments
Labels
bug Something isn't working Typescript issues to do with TS

Comments

@arswaw
Copy link

arswaw commented Dec 20, 2023

Discussed in #3121

Originally posted by arswaw December 14, 2023
Hello. I am using R3F for the first time and I am also using TypeScript. All my component files have the .tsx extension.

I have run into an issue with useRef and this may affect other attributes.

Consider the following code:

<mesh ref={cubeRef} rotation-y={Math.PI * 0.25} position-x={2} scale={1.5}>
   <boxGeometry />
  <meshBasicMaterial color="mediumpurple" />
</mesh>

If I define useRef in the same component like:

const cubeRef = useRef()

Then ref in the <mesh ... /> will return the following error:

Type 'MutableRefObject<undefined>' is not assignable to type 'Ref<Mesh<BufferGeometry<NormalBufferAttributes>, Material | Material[], Object3DEventMap>> | undefined'.
  Type 'MutableRefObject<undefined>' is not assignable to type 'RefObject<Mesh<BufferGeometry<NormalBufferAttributes>, Material | Material[], Object3DEventMap>>'.
    Types of property 'current' are incompatible.
      Type 'undefined' is not assignable to type 'Mesh<BufferGeometry<NormalBufferAttributes>, Material | Material[], Object3DEventMap> | null'.ts(2322)
three-types.d.ts(34, 5): The expected type comes from property 'ref' which is declared here on type 'MeshProps'
(property) ref?: React.Ref<Mesh<BufferGeometry<NormalBufferAttributes>, Material | Material[], Object3DEventMap>> | undefined

The problem is that React useRef is typed like:

function useRef<T = undefined>(): MutableRefObject<T | undefined>;

Whereas in r3f/node_modules/@react-three/fiber/dist/declarations/src/three-types.d.ts we see:

export interface NodeProps<T, P> {
    attach?: AttachType;
    /** Constructor arguments */
    args?: Args<P>;
    children?: React.ReactNode;
    ref?: React.Ref<T>;
    key?: React.Key;
    onUpdate?: (self: T) => void;
}

If ref (and perhaps related attributes) were typed:

ref?: React.Ref<T | undefined>

then it would solve the problem.

When I modified the R3F dependency directly, the error disappeared.

Since that is bad practice, I have used the temporary solution:

const cubeRef = useRef() as MutableRefObject<Mesh>

However this decreases type safety since the ref could return undefined at runtime.

I am not sure if I am in misinterpreting the problem or the solution. Does my new union type make sense?

@ksoldau
Copy link

ksoldau commented Mar 26, 2024

I am experiencing the same issue with "@react-three/fiber": "^8.15.19".

@CodyJasonBennett
Copy link
Member

I think the type we use in R3F is wrong and should allow undefined. We can align with the DOM types on this.

@filahf
Copy link

filahf commented Apr 16, 2024

I think this might be the correct behavior, you'll get the same error with a regular DOM element. You need to type your ref like this and init with null. (React will set ref.current = null when the component unmounts)

export const Component = () => {
	const ref = useRef<Mesh>(null);

	return <mesh ref={ref} />;
};

Respectively, this is how you would type a ref to a div

export const Component = () => {
	const ref = useRef<HTMLDivElement>(null);

	return <div ref={ref} />;
};

@CodyJasonBennett
Copy link
Member

This will be fixed with React 19. Looks like this was an upstream issue.

@CodyJasonBennett CodyJasonBennett added the bug Something isn't working label Apr 28, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working Typescript issues to do with TS
Projects
None yet
Development

No branches or pull requests

4 participants