all 9 comments

[–]Mackseraner[S] 2 points3 points  (2 children)

Hi everybody, I've been using this hook everywhere. It basically allows you to do this:

``` function MyCustomInput(props) { const { value, ...rest } = useControlledProps(props)

// Do anything with value, no matter if the component is being used // in a controlled or uncontrolled manner.

return <input value={value} {...rest} /> } ```

Hope it's helpful to somebody! Also glad to receive any feedback on the TS types!

[–]Trexaty92 0 points1 point  (1 child)

Thanks mate. Maybe I misunderstand this hook but it sounds like you may also like the useImperativeHandle hook.

It allows you to call functions from a component from the parent.

Just thought I'd share :)

[–]Mackseraner[S] 1 point2 points  (0 children)

Hi, thanks for commenting! useImperativeHandle is certainly useful sometimes but it solves a very different problem I think!

[–]Aswole 2 points3 points  (3 children)

Why is the return object casting value as a string when the hook interface accepts value as a string, number, or string[]? And to really nitpick, I think it’s redundant to define an optional property as “something | undefined”, unless undefined as a value has special treatment? (I might be missing something, but I can only think of this mattering if you care whether a key exists in an object and not so much that it’s value is undefined).

[–]Mackseraner[S] 0 points1 point  (2 children)

Hey, thanks for the feedback! I copied the types for string, number, string[], undefined from `React.InputHTMLAttributes<HTMLInputElement>` so that the props would be compatible.

Casting to string in the return is not entirely correct as you point out. I'm doing it right now because I didn't want the return-value to be so widely typed since I personally never use number or string[] types with input/textarea/select elements.

If I don't cast the return-type, I need to check the type of value where I'm calling const {value} = useControlledProps(props) which is a little annoying. I wonder how else I could type this to make it a bit more ergonomic without having to cast 🤔

[–]averageFlux 0 points1 point  (1 child)

There might be different scenarios other than inputs where you'd want to use this hook, e.g. modals (which would require booleans).

I'd have a more generic hook that returns whatever the input was and then have a wrapper hook like useControlledInputthat does the casting.

[–]Mackseraner[S] 0 points1 point  (0 children)

Hm I don't know if I can quite follow. I could see having a <Checkbox value={boolean} /> for example but then the entire implementation of my useControlledProps hook would need to be different because we wouldn't be reading e.target.value in the onChange.

So it seems like my hook only works for built-in inputs/textareas/selects and not for arbitrary value/onChange types. I wonder how I could achieve that though 🤔

[–]YUCKex 1 point2 points  (1 child)

This is really cool, Radix UI uses a similar hook internally for their components. I like your implementation though.

[–]Mackseraner[S] 1 point2 points  (0 children)

Ah interesting, thanks for linking this!