메신저나 일반적인 웹앱의 댓글에서 보면 입력한 내용의 줄 개수에 따라 인풋 상자의 크기가 변하는 것을 확인할 수 있다. 카톡의 경우 무한대로 늘어나는 것은 아니고 최대 5줄까지 반영되어 길이가 늘어나고 그 이상의 인풋값이 들어오면 스크롤로 대체된다.
useRef
로 간단하게 위 기능을 구현해볼 수 있다.
function Form() {
const inputRef = useRef<HTMLTextAreaElement>(null);
const handleHeight = () => {
// inputRef의 scrollHeight 최대값을 100으로 제한
if (inputRef && inputRef.current && inputRef.current.scrollHeight < 100) {
inputRef.current.style.height = `${inputRef.current.scrollHeight}px`;
}
}
return (
<TextInput
ref={inputRef}
value={text}
onKeyDown={handleHeight}
onKeyUp={handleHeight}
/>
)
}
inputRef
가 TextInput
을 바라보게 하고, 해당 값의 scrollHeight
가 textarea의 height
값이 되도록 지정해준다. 조건에 최대값만 걸어주면 끝! 쏘 심 플 !
추가로 useRef
를 사용하여 옵션에 따라 인풋에 자동으로 포커스가 될 수 있도록 하는 기능을 구현해보았다. 여러 옵션이 있고, 마지막에 '기타' 옵션을 선택시 추가로 인풋을 입력하게 하는 경우에 유용하게 사용할 수 있다.
function Survey() {
const [option, setOption] = useState('choice1');
const inputRef = useRef<HTMLTextAreaElement>(null);
useEffect(() => {
if (inputRef && inputRef.current && option === 'choice5') {
inputRef.current.focus(); // choice5 선택시 input 자동 포커스!
}
}, [option]);
return (
<>
{
OPTIONS.map(({ title, value, id }) => (
<Radio
type='radio'
onClick={() => setOption(value)}
value={value}
id={id}
name='choice'
/>
)
}
<TextInput ref={inputRef} disabled={option !== 'choice5'} />
</>
);
}
useRef
너무 좋다... 👍