[CSS, react, useRef] useRef를 사용하여 textarea 자동 높이조절 하기(엔터키, delete 키 입력시)
먼저, 전체 코드를 보여드리면 App.js와 AutoHeight.js 는 이렇다.
App.js
import { useRef } from "react";
import AutoHeight from "./AutoHeight";
function App() {
return (
<div>
<AutoHeight />
</div>
);
}
export default App;
AutoHeight.js
import React, { useState, useRef } from "react";
function AutoHeight(props) {
const inputTag = useRef(null);
const longerTextArea = (event, tag) => {
if (event.keyCode === 13 || 8) {
tag.current.style.height = `auto`;
tag.current.style.height = `${inputTag.current.scrollHeight}px`;
}
};
return (
<textarea
ref={inputTag}
placeholder={"댓글을 입력해주세요"}
onKeyUp={(event) => longerTextArea(event, inputTag)}
></textarea>
);
}
export default AutoHeight;
App.js에 들어갈 컴포넌트 형태로 AutoHeight를 구현했고, 이 코드대로 입력하면 자동높이조절 기능만 있는 조그마한 박스가 나온다.
이를 구현하기 위해서는 먼저 useRef를 알아야 한다. ref는 해당 태그에 있는 속성에 접근할 수 있게 해준다. 따라서 여기선 <textarea> 태그에 ref = {inputTag}를 썼지만 만약 <div>태그에 쓰고 싶다면 <div ref = {inputTag}></div> 라고 쓸 수 있을것이다. 물론 inputTag라는 이름 자체는 본인이 어떻게 선언하느냐에 따라서 이름이 달라질 수 있다. 예를들어
const clickTag = useRef(null) 이라고 선언한뒤 <div ref = {clickTag}></div> 라고 참조를 할 수도 있는것이다. 이는 getElementById()함수와도 매우 흡사하다.
이렇게 ref를 원하는 tag(여기선 textarea)에 걸어준 뒤에는 그 tag의 속성에 접근할 수 있다. 원하시는 분들은 한번 console.log(inputTag.current)를 해보면 어떠한 의미인지 아실 수 있을 것이다!
여기서 하고자하는건 useRef로 할 수 있는 다양한 것중에 textarea의 CSS에 접근하는 것이다.
return (
<textarea
ref={inputTag}
placeholder={"댓글을 입력해주세요"}
onKeyUp={(event) => longerTextArea(event, inputTag)}
></textarea>
);
이때에, 우리의 목적은 엔터를 치면 그만큼 높이가 늘어나고 delete를 하면 그만큼 높이가 줄어드는 박스를 만드는 것이므로 textarea에서 onKeyup이란 이벤트함수를 통해 키보드에서 enter가 들어오는지, delete가 들어오는지 아니면 다른 키보드 입력이 들어오는지를 먼저 확인해줄 필요가 있다. 이때 event라는 인자는 onKeyUp으로부터 자동으로 받게되며 이 event를 longerTextArea라는 우리가 만들 함수의 인자로 다시 넘겨주었다.
const longerTextArea = (event, tag) => {
if (event.keyCode === 13 || 8) {
tag.current.style.height = `auto`;
tag.current.style.height = `${inputTag.current.scrollHeight}px`;
}
};
이후에 우리의 목적인 longerTextArea라는 함수를 만들기 시작했다.
먼저 console.log(event.keyCode) 를 하여 각각의 키보드마다 어떤 값으로 입력이 되는지를 알아야한다. 확인해본 결과 enter키를 쳤을때 event.keyCode 는 13이였고, delete를 쳤을때는 8이였다. 따라서 if(event.keyCode === 13 || 8) 로 13혹은 8일때만 반응하게끔 했다.
inputTag를 longerTextArea에 두번째 인자로 넘겨주었고 이를 tag라는 이름으로 받았다. 그리고 console.log(tag.current.style) 을 통해 확인하여 tag.current.style로 useRef를 한 태그의 css에 접근할 수 있다는 것을 알 수 있다.
tag.current.style.height 에 우리가 접근하여 높이를 조절할 수 있는 것이다. 이때, 스크롤 바의 높이인 scrollHeight는 inputTag.current.scrollHeight로 찾을 수 있고, 박스 자체의 높이는 tag.current.style.height로 찾을 수 있다.
여기서 중요한 것은 tag.current.style.height = auto 인데, 이때의 의미는 안에 들어가는 텍스트의 크기에 맞춰 박스 높이를 조절하라는 의미이다. 이 줄을 주석처리하면 delete를 해도 높이가 줄어들지 않으므로 반드시 넣어야 한다.
두번째줄에는 tag.current.style.height = `${inputTag.current.scrollHeight}px`; 를 넣어서 스크롤의 높이(scrollHeight)만큼 높이를 조절해준다. 이때, ` ` 이 기호를 써서(tab키 위에 있는 `버튼, ~와 함께 있는 그 버튼) 변수 inputTage.current.scrollHeight를 받고 반드시 뒤에 px을 붙여주자. px을 붙이지 않으면 인식을 안하기 때문이다.
이렇게 완료하고 나면 위와같은 사진처럼 안에 내용물에 따라, 그리고 enter와 delete를 입력함에 따라 textarea의 높이가 달라짐을 확인할 수 있다.
감사합니다 :)