-
Notifications
You must be signed in to change notification settings - Fork 1.2k
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
provide more accurate types for useTextField #1761
Conversation
If this approach is okay I will update Though I do wonder if it's necessary to have Even so doing |
It looks similar to what I'd been expecting for the other issue. |
The types currently allow for both react-spectrum/packages/@react-aria/searchfield/src/useSearchField.ts Lines 22 to 40 in e066b67
If I remove Same for |
O interesting, I didn't notice it already had it, that makes it more complicated :( I think we'll have to have the overloads for both so it's not a breaking change. |
Sure no problem. I'll implement the function overloads for both I just wanted to make sure that the approach would be considered for merging before I went to the trouble 🙂 |
@snowystinger I have pushed up the changes for I will note - it seems better to make this a breaking change and to not allow Textarea for these hooks. It really doesn't make sense and it really complicated the types (for example, I'm unhappy with the use of Also of note I had to change ComboBox.tsx and SearchField.tsx as these allowed a ref of It's also noteworthy that until the parcel build is fixed (#1388) such that overloads are properly included in the types.d.ts file that this change is a little moot - since sometimes the returned I believe that the lint step in the CI is failing due to the missing types from the parcel build (#1388) Please let me know of any feedback or anything you'd like me to address here |
I unfortunately need to withdraw my PR. We have begun to unwind our usage of react-aria due to issues with types and reliance on React Stately. Using react-aria outside of React Spectrum is quite difficult when not conforming to the design considerations made for React Spectrum. |
@chrishoage I'm sorry to hear that. I also apologize for not getting back to your PR. If you don't mind, could you expand on the problems you ran into aside from the type changes in this PR? What were your issues with React Stately, and what did you find difficult to use? |
@devongovett Sure, happy to! By far the biggest issue is the well-baked in pattern of passing in all props to the hooks, and then getting a bag of unknown props back. A goal for our component library was strict types, and every single hook in react-aria returning I'm going to pick on react-spectrum/packages/@react-aria/overlays/src/useOverlayTrigger.ts Lines 60 to 68 in 9aab12e
The return value of react-spectrum/packages/@react-aria/overlays/src/useOverlayTrigger.ts Lines 28 to 29 in 9aab12e
Which means that we can't know what types could possibly come from the hook with out inspecting the source. This became particularly problematic when trying to use As for React Stately, the issue was our company ESLint rules which among other things require dependencies be added to react hook dependency arrays. We wished to extend There were some other issues too, most notability no support for nested menus with Ultimately we kept In summary, the issues were around a need for strong type signatures and extensibility that doesn't break when used with hooks that require sable dependencies. If we were construing our component library in the way React Spectrum is constructed I'm sure it would would great. However our requirements lead to conflicts with how the react-aria library fundamentally works. Hope this was helpful, and thank you for your work on this project! |
@chrishoage thanks so much for the detailed feedback! Just for context about the reasoning for returning As for memoizing the return values of stately hooks, that's definitely something we should look into. |
I'm running into a similar difficulty. It is difficult to understand what React-ARIA actually does when the return types of its hooks don't provide meaningful signal. My team is also building a ui library and we might not be able to continue down the React-ARIA path, as much as we like the project otherwise. edit: looks like the React-Stately issue is going to apply to us too, since we also use the same eslint rule (enabled by default on apps created w/ create-react-app) |
@bstro do you have any ideas for how to handle the above issues re breaking changes whenever we add/remove DOM attributes? What specifically are you having difficulty with? |
Apologies for my lack of specificity—I first encountered the same interop issue w/ Framer Motion as @chrishoage described. I don't really have a suggestion yet for how to solve the breaking change consideration, but I'll give it some thought! As a downstream user of this library, I would personally prefer more accurate types, and if/when breaking api changes occur, I would read the release notes for how to update my code. Granted, I've never worked on a library of this size and scope, so that might be a naive take. |
I have two ideas, but first I want to clarify my own understanding: My understanding is that the current API encourages users to spread the entirety of the props returned by React-ARIA's hooks directly into the React element i.e. My first thought is, if the above is true, would it work to use the Pick utility to narrow the relevant properties of Here's another idea, I have no idea if it's workable or not, but what about exposing the same hooks with stricter types under a different name? These hooks would have the exact same implementation, but have narrower/accurate types. For example, in addition to |
Right, Say we added an event handler or new DOM attribute to the return type of a hook in a minor release. If those props are being spread onto an element that doesn't expect that attribute, the build will fail and it could be considered a breaking change. Because we tell you to spread, basically any time we add anything it could be breaking. That's why we reserve all DOM attributes for potential use. You work out once how to pass DOM attributes through to your components, and never need to worry about it again, vs potentially having to worry about it whenever your React Aria version changes. To be clear, we struggle with how to handle this sometimes in our own component library. We don't want to expose all DOM attributes as part of the public API, but if we want to reuse that component in another component and need to pass through some DOM props it becomes difficult. We've tried a couple different approaches:
As for interop with other libraries... I'm not sure what the solution is. I'm a bit surprised Framer's Again, I'm open to more ideas here, but I think we need to be careful about this so we don't shoot ourselves in the foot down the road. |
I guess an obvious solution would be to have the props defined as interface ButtonAria {
buttonProps: any
} That seems a little weird and might potentially cause other issues though. I noticed that Downshift does this though: https://github.com/downshift-js/downshift/blob/master/typings/index.d.ts#L341 |
material-ui's hooks do the same as React Aria: https://github.com/mui-org/material-ui/blob/ef6d5d46bade437f155ce96d7403086cb50f52ef/packages/material-ui-unstyled/src/AutocompleteUnstyled/useAutocomplete.d.ts#L308-L322 |
Thanks for the thoughtful reply and context. That's really interesting re: material-ui. I see what you mean for their |
Yeah looks like they didn't define any types in that one, just relying on inference. |
Closes mui/material-ui#1760
This PR uses Function Overloads to support both Textarea and Input elements in
useTextField
.If the approach is approvied there will need to be a tweak to the eslint config to allow for overloads https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-redeclare.md(I discovered the precedent of eslint-disable lines inuseButton
)I also think this might open up support for closing #1178 since the overload should allow props that only apply to Textarea or Input however I haven't attempted to solve that yet.
In order to achieve fixing that there will need to be a split of
AriaTextFieldProps
intoAriaTextFieldInputProps
andAriaTextFieldTextareaProps
such that the overload will allow only Textarea props when the signature matches.I'm happy to tweak this as needed
✅ Pull Request Checklist:
📝 Test Instructions:
No regressions in
useTextField
Case described here works https://codesandbox.io/s/affectionate-bardeen-rtfmw
🧢 Your Project: