리액트는 기본적으로 DOM을 직접 조작하지 않지만 특정한 경우 DOM을 직접 조작해야하는 경우가 있다.
일반 자바스크립트에서는 특정 DOM에 id를 부여해서 조작을 할 수 있지만 리액트에서는 권장되지 않는 방법이다. 컴포넌트 안에 있는 특정 DOM에 id를 부여할 경우 그 컴포넌트를 여러개 호출 할 시 id가 중복될 수 있다.
따라서 리액트에 id와 같이 특정 이름을 부여할 경우에는 ref라는 속성을 사용한다. ref는 컴포넌트 내부에만 작용을 하기 때문에 id 중복 문제가 생기지 않는다.
ref를 사용해야하는 경우는 다음과 같다
ref를 설정하는 방법은 두 가지가 있다
ref를 달고자 하는 요소에 ref라는 콜백 함수를 props로 전달해 주면 된다
예시는 다음과 같다
<input ref={(ref)} => {this.input=ref}></input>
리액트에 내장되어 있는 createRef를 사용한다 이 기능은 리액트 v16.3부터 추가되어서 이전 버전에서는 사용이 안된다고 한다. 콜백 함수를 사용하는 경우와는 다르게 current로 DOM을 조작하면 된다.
import React, { Component } from "react";
class createRef extends Component {
input = React.createRef();
handleFocus = () => {
this.input.current.focus();
};
render() {
return (
<div>
<input ref={this.input}></input>
</div>
);
}
}
export default createRef;
또한 ref는 DOM 뿐만 아니라 컴포넌트에도 설정할 수 있다 이렇게 설정 할 경우 내부 메소드 및 멤버 변수, 내부에서 설정한 ref에도 접근이 가능하다.
App.js
import {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>
)
}
}
exfault default App;
ScrollBox.js
import React, { Component } from "react";
export default class ScrollBox extends Component {
scrollToBottom = () => {
const { scrollHeight, clientHeight } = this.box;
this.box.scrollTop = scrollHeight - clientHeight;
};
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>
<div
style={style}
ref={(ref) => {
this.box = ref;
}}
>
<div style={innerStyle}></div>
</div>
</div>
);
}
}
App.js에서 ScrollBox 컴포넌트 태그에 ref를 설정하고 버튼을 클릭 할 시 ScrollBox 내부에 있는 ref에 접근해서 스크롤 상자를 맨 밑으로 이동할 수 있다.
함수형 컴포넌트에서는 ref를 설정하려면 useRef라는 함수를 사용해야한다고 한다.
import React, { useRef } from "react";
import ScrollBox from "./components/ScrollBox";
const App = () => {
const scrollBox = useRef();
return (
<div>
<ScrollBox ref={scrollBox}></ScrollBox>
<button
onClick={() => {
scrollBox.current.scrollToBottom();
}}
>
맨 밑으로
</button>
</div>
);
};
export default App;