티스토리 뷰
ref: DOM에 이름 달기
리액트에서는 HTML의 요소인 id를 사용할 수 없다. 왜냐하면 id는 고유한 값인데 컴포넌트를 여러 번 사용할 경우 id의 고유성을 잃기 때문이다. 하지만 그렇다고 id 자체를 사용하지 못하게 된다면 그것 또한 문제이기 때문에 리액트에서는 ref라는 기능을 사용한다.
ref는 전역적으로 작동하지 않고 컴포넌트 내부에서만 작동하기 때문에 위와 같은 문제에 대처 가능하다. 이렇게 id처럼 쓸 수 있으니 다른 라이브러리나 프레임워크와 함께 잘 사용이 가능하다. 그렇다면 ref는 언제 사용하면 좋은걸까?
DOM을 꼭 직접적으로 건드려야 할 때 입니다. 보통은 아래와 같은 경우에 자주 사용된다.
- 특정 input에 포커스 주기
- 스크롤 박스 조작하기
- Canvas 요소에 그림 그리기 등
ref 사용: 콜백 함수를 이용한 설정
가장 기본적인 방법이 콜백함수를 이용하는 것이다. ref를 달고자 하는 요소에 ref라는 콜백 함수를 props로 전달해 주면 됩니다. 이 콜백 함수는 ref값을 파라미터로 전달받습니다. 그리고 함수 내부에서 파라미터로 받은 ref를 컴포넌트의 멤버 변수로 설정해 줍니다.
<input ref ={ (ref) => {this.input=ref} } />
이렇게 하면 앞으로 this.input은 input 요소의 DOM을 가리킵니다. ref의 이름은 원하는 것으로 자유롭게 지정할 수 있습니다. DOM 타입과 관계 없이 this.superman = ref처럼 마음대로 지정합니다.
ref 사용: createRef를 통한 설정
16.3부터 적용된 이 기능은 이전 버전에서는 작동하지 않습니다. 우선 아래의 코드를 살펴봅시다.
import React, { Component } from "react";
class refSample extends Component {
input = React.createRef();
handleFocus = () => {
this.input.current.focus();
};
render() {
return (
<div>
<input ref={this.input} />
</div>
);
}
}
export default refSample;
컴포넌트 내부에서 멤버 변수로 React.createRef()를 담아주어야 합니다. 그리고 달고자하는 요소에 ref props로 넣어주면 설정이 완료됩니다. 콜백함수와 다른점은 뒷부분에 .current를 넣어주어야 하는 것입니다.
컴포넌트에 ref 달기
이 방법은 주로 컴포넌트 내부에 있는 DOM을 외부에서 사용할 때 사용합니다.
<MyComponent
ref ={(ref) => {this.myComponent=ref} }
/>
이렇게 하면 MyComponent 내부의 메서드 및 멤버 변수에도 접근할 수 있습니다. 즉, 내부의 ref에도 접근할 수 있습니다. 이번에는 스크롤 박스가 있는 컴포넌트를 하나 만들고, 스크롤바를 아래로 내리는 작업을 부모 컴포넌트에서 실행해 보겠습니다.
import React, { Component } from "react";
class ScrollBox extends Component {
render() {
const style = {
border: "1px solid black",
height: "300px",
width: "300px",
overflow: "auto",
position: "relative"
};
const innerStyle = {
width: "100%",
height: "650px",
background: "linear-gradient(white, black)"
};
return (
<div
style={style}
ref={ref => {
this.box = ref;
}}
>
<div style={innerStyle} />
</div>
);
}
}
export default ScrollBox;
ㅇ이제 컴포넌트에 스크롤바를 맨 아래쪽으로 내리는 메서드를 만들어 봅시다. 자바스크립트로 스크롤바를 내릴 때는 DOM 노드가 가진 다음 값들을 사용합니다.
- scrollTop: 세로 스크롤바 위치(0~350)
- scrollHeight: 스크롤이 있는 박스 안의 div 높이(650)
- clientHeight: 스크롤이 있는 박스의 높이(300)
스크롤바를 맨 아래로 내리려면 scrollHeight에서 clientHeight를 빼면 되지요.
class ScrollBox extends Component {
scrollToBottom = () => {
const { scrollHeight, clientHeight } = this.box;
this.box.scrollTop = scrollHeight - clientHeight;
};
render() {
import React, { Component } from "react";
import ScrollBox from "./ScrollBox";
class App extends Component {
render() {
return (
<div>
<ScrollBox ref={ref => (this.scrollBox = ref)} />
<button onClick={() => this.scrollBox.scrollToBottom()}>맨 아래로</button>
</div>
);
}
}
export default App;
이렇듯 ref로 DOM에 직접 접근이 가능하지만 이걸 사용하지 않고 원하는 기능을 구현할 수 있는지 반드시 고려한 후에 사용하십시오. 서로 다른 컴포넌트끼리 데이터 교류할 때 ref를 사용한다면 이는 잘못 사용된 것입니다. 리액트 사상에 어긋나는 설계방식이지요. 앱 규모가 커지면 구조가 꼬여서 유지보수가 불가능이 되어버릴지도 모릅니다.
출처: 리액트를 다루는 기술
'front-end > React' 카테고리의 다른 글
리액트 라이프 사이클 (0) | 2019.12.06 |
---|---|
리액트 컴포넌트의 반복 (0) | 2019.12.06 |
리액트 이벤트 조작([e.target.name] : e.target.value) (0) | 2019.12.04 |
리액트 State (0) | 2019.12.03 |
리액트 컴포넌트와 props (0) | 2019.12.03 |