Use React.forwardRef in Typescript with no props
Asked Answered
U

3

8

I'm trying to forward a ref to a Typescript component that does not take any props. When I use React.forwardRef it takes two parameters: props and ref. My component does not use props. How can I declare my component with no linting or compilation errors?

Right now I have:

// this says "props is declared but its value is never used"
const MyComponent = React.forwardRef((props = {}, ref: Ref<HTMLDivElement>): JSX.Element => {
  return (
      <div ref={ref}>
        Fun stuff
      </div>
  );
});

If I declare an empty interface for my props like this:

interface myProps {}

Then I get An empty interface is equivalent to '{}' but then when I try to declare with just {} and no actual interface then I get:

Don't use `{}` as a type. `{}` actually means "any non-nullish value".
- If you want a type meaning "any object", you probably want `Record<string, unknown>` instead.
- If you want a type meaning "any value", you probably want `unknown` instead.

Is there some way that I can declare an interface/type for these props which expects an empty object and doesn't cause me linting issues?

Update: When I use an empty object type as recommended from this issue thread, it causes a type error where the component is used.

Type '{ ref: RefObject<HTMLDivElement>; }' is not assignable to type 'Pick<NoElements<Record<string, never>>, string>'.
  Property 'ref' is incompatible with index signature.
    Type 'RefObject<HTMLDivElement>' is not assignable to type 'never'.

Shows at:

<MyComponent ref={refToForward} />

Seems like there's a chicken egg situation.

Unchurch answered 20/10, 2020 at 16:35 Comment(1)
what if you used React.forwardRef<HTMLDivElement, any>() instead?Arni
S
6

If you want to use forwardRef but don't need props, you can try this:

const MyComponent = forwardRef((_: unknown, ref: Ref<HTMLDivElement>) => {
  return (
      <div ref={ref}>
        ...
      </div>
  );
});
Servant answered 11/9, 2022 at 11:8 Comment(1)
Changing from _props: undefined to _props: unknown fixed it for me.Benevolent
V
0

You could prefix the props with an underscore like this _props to get rid of props is declared but its value is never used.

And for the empty interfaces I usually use types, so, in your case, that would be type myProps = {}.

UPD:

How about we pass the types into the <>, like:

type Props = {};

const MyComponent = React.forwardRef<HTMLDivElement, Props>((props, ref) => {
  return (
      <div ref={ref}>
        Fun stuff
      </div>
  );
});
Val answered 20/10, 2020 at 18:10 Comment(8)
Using a type still gives me an error: Don't use {} as a type. {} actually means "any non-nullish value". - If you want a type meaning "any object", you probably want Record<string, unknown> instead. - If you want a type meaning "any value", you probably want unknown instead.Unchurch
Ok, so I looked into it and it appears you're using typescript-eslint config. Basically, what are you trying to do is not encouraged in the comments of the repo, but you could always // eslint-disable-next-line to get rid of the messages or reconfigure your .eslintrc file: { "rules": { "@typescript-eslint/ban-types": [ "error", { "extendDefaults": true, "types": { "{}": false } } ] } }Val
Basically, what are you trying to do is not encouraged in the comments of the repo. What exactly isn't encouraged? Do you have a link? Is an alternative suggested somewhere?Unchurch
Sure, here it is github.com/typescript-eslint/typescript-eslint/issues/… look at the last section of the comment by bradzacher and let me know if it means something else, cause I would want to know too :)Val
I guess the recommended way would be to define props of the component, but since you want to omit them it's better to either reconfigure the eslint or disable that particular rule on that particular lineVal
That issue you referenced is VERY helpful. I think the preferred solution here would be to use one of the empty object types that are listed there. I need to play with it a bit more to see which would work best then I'll let you know and you can edit this answer.Unchurch
Hmm, adding the empty object type gives me an error where the component is used. I feel like I'm going in circles here. See the updated question.Unchurch
I think you might want to change the approach of defining the types of forwardRef, so check out the upd in the answerVal
R
0

For me, it worked with an underscore after using ref due to this lint rule after-used argument at https://eslint.org/docs/latest/rules/no-unused-vars#args-after-used which roughly states that the previous param will not be checked if the next one is used. I know it's a little late question but hope this answer helps someone though.

Roar answered 1/2 at 18:43 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.