28 December 2023
In my 6 years career I almost never had to make an autogrowing textarea field like the ones we have in Jira or Linear (i.e. description fields) 👇
But recently, I had to make one. While there are already some posts about this, e.g. THIS post by Owen, I thought I'd post my solution, which covers a slightly different scenario.
So basically, I create a hook
export const useInputHeight = (name: string, value: string | undefined) => { const setInputHeight = useCallback(() => { const textarea: HTMLTextAreaElement | null = document.querySelector(name); if (!textarea) return; textarea.style.height = textarea.scrollHeight + "px"; }, [name]); useEffect(() => { setInputHeight(); }, [value, setInputHeight]); return setInputHeight; };
It returns a setInputHeight
function that we call in our onChange
function.
const setNameInputHeight = useInputHeight('textarea[name="email"]', emailValue); // ... const handleInputChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => { setInputHeight(); // ... other functionality };
Do you need a value
argument? No, you don't, but in my case, the value was being updated on the client, so I had to adjust the field height every time it updated without me triggering the onChange
event.
If that's not the case, simplify it to be
export const useInputHeight = (name: string) => { const setInputHeight = () => { const textarea: HTMLTextAreaElement | null = document.querySelector(name); if (!textarea) return; textarea.style.height = textarea.scrollHeight + "px"; }; return setInputHeight; };
That's all you'd need.
You may have also noticed that I'm not using useRef()
and simply doing document.querySelector
.
Would ref
work? Yes, yes it should. The only reason I was using querySelector
was because I was using a UI library and textarea there wasn't allowing a ref
prop. So I didn't want to do all those workarounds, querySelector
seemed like a great option.
Do feel free to use a ref
if you'd like, after all, it IS a more 'React way' of doing things 😁👍