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 😁👍
Top comments (0)