-
-
Notifications
You must be signed in to change notification settings - Fork 227
Allow ref objects to be passed #308
Allow ref objects to be passed #308
Conversation
5867eb9
to
a0b407e
Compare
// React refs are supposed to be contravariant (allows a more general type to be passed rather than a more specific one) | ||
// However, Typescript currently can't infer that fact for refs | ||
// See https://github.com/microsoft/TypeScript/issues/30748 for more information | ||
ref: React.Ref<any>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is very unfortunate, but this issue with contravariance vs covariance with refs is a very long standing issue with TS that doesn't look like it will be resolved soon.
a0b407e
to
d221826
Compare
type RefHandler = (?HTMLElement) => void; | ||
type RefObject = { current?: HTMLElement}; | ||
|
||
export type Ref = RefHandler | RefObject; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why can't we use React$Ref<HTMLElement>
here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
React$Ref<HTMLElement>
includes string refs which are legacy and react-popper does not support.
@maclockard would be awesome if you add test for this 👍 |
Added tests! Ended up needing to bump some of the test versions to properly support ref objects, so theres a bit more churn on the snapshots than I would like, but that's needed for #303 anyway. Still something a little bit funky with the flow typings since it doesn't recognize |
a86c9c6
to
df9f43a
Compare
@FezVrasta rebased this PR on top of master, could you take a look? |
@FezVrasta do you think you will have time to look at this soon? |
I have code like this: <Reference>
{({ ref }) => <Button ref={(r) => { ref(r); buttonRef.current = r; }} toggle={toggle} />}
</Reference> Which now reports an error:
Is there a suggested change I should make? |
@shepmaster What versions of react and react popper are you using? Is this in a function component or a class component? Is |
@maclockard sorry for the initial lack of information!
The code currently appears to work (e.g the "Debug" menu button). Thanks! |
@shepmaster the code you have is correct in the sense that it will run, but its just failing a type check. The A way to fix this is for you to add a type guard to provide TS with enough information to know that function isRefObject<T>(ref: React.Ref<T>): ref is RefObject<T> {
return ref !== null && typeof ref !== 'function';
} An other (worse) solution would be to change the type of |
Another (probably better) solution is that react-popper provides an So your code would look like this: <Reference innerRef={buttonRef}>
{({ ref }) => <Button ref={ref} toggle={toggle} />}
</Reference> |
Ah, that works wonderfully, thank you! For future readers, there's also an Now I'll have to wonder if those were always there and I missed them on my original implementation or what... 😉 |
Fixes #307
I tested this locally with my app using
yarn link
and everything worked!