-
-
Notifications
You must be signed in to change notification settings - Fork 32.5k
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
[InputUnstyled] Fix externally provided inputRef
is ignored
#35807
Conversation
|
Signed-off-by: Zeeshan Tamboli <zeeshan.tamboli@gmail.com>
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.
Thanks @sai6855 ! Looks good!
Thanks for the review!! |
inputRef
is ignored
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.
Shouldn't this prop comes from the slotProps.input.ref
instead? cc @michaldudak
Yes, this was a general idea. In the case of the Unstyled Input, I suspect that using a |
typeof slotProps.input === 'object' && typeof slotProps.input.ref !== 'undefined' | ||
? slotProps.input.ref | ||
: undefined, |
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 the best i could do to make typescript happy
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 do you need to pass ref from slotPros.input.ref? It will be forked in useSlotProps for Input.
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 do you need to pass ref from slotPros.input.ref?
If someone wants to provide their own ref to the InputUnstyled, they'd do it with the slotPros.input.ref
.
this is the best i could do to make typescript happy
Ah, I see, we've got a bit of a chicken and egg problem here - slotProps
possibly need ownerState
, which needs useInput
result, which depend on slotProps
. We have to do this differently, then. Do not pass inputRef
to useInput
, but add it to input slot's useSlotProps' additionalProps
object. The useSlotProps hook should take care of merging it correctly with the result of useInput.
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.
So it turns out we don't need to pass slotProps.input.ref
in additional props. externalProps
(i guess) in the same hook is taking care of passing ref
to useInput
. All we have to do is destructure ref and fork :)
Added test to make sure input element is attached to ref.
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.
Indeed! I forgot what functionality I added to useSlotProps ;)
@ZeeshanTamboli @michaldudak updated code as suggested. |
@mnajdova @michaldudak So then, implementation-wise, should we remove the inputRef: slotProps.input?.ref ?? inputRefProp |
Remove it from the interface, it was anyway not handled, so I would say it was broken even before. We can anyway list is a breaking change, because of the type change. |
It is extremly useful feature for developers who create custom components based on useInput hook because in other case you have no any possibility to get ref for input element but to call getInputProps. Maybe it is better continue support it, just handle ref inside the hook? |
We can leave the |
Then I guess no changes is required for PR, current state of PR does exactly as you described |
Actually, as I commented in #35807 (comment), |
Please, check PR |
it('should be able to attach input ref passed through props', () => { | ||
const inputRef = React.createRef<HTMLInputElement>(); | ||
const { getByRole } = render(<InputUnstyled slotProps={{ input: { ref: inputRef } }} />); | ||
expect(getByRole('textbox')).to.deep.equal(inputRef.current); |
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.
Just to make sure input element is attached to ref.
previously test is written as
expect(inputRef.current).not.to.equal(null)
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.
We could use one more test to verify the behavior of useInput alone. See https://github.com/mui/material-ui/pull/35880/files#r1082379077
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.
Done
} | ||
const { getByRole } = render(<Input />); | ||
|
||
expect(getByRole('textbox')).to.deep.equal(inputRef.current); |
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 should be the other way around:
expect(getByRole('textbox')).to.deep.equal(inputRef.current); | |
expect(inputRef.current).to.deep.equal(getByRole('textbox')); |
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.
Updated
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.
Thanks!
closes: #35783