ref 는 특정 DOM을 직접 건드리고 싶은 경우에 지정해 사용한다. DOM을 조작할 때 getElementById 혹은 querySelector 등을 사용해 노드를 선택하고 이를 변수에 담아 활용했다. 하지만 특정 DOM을 직접 찍어 이를 활용하고 싶은 경우 ref 를 활용할 수 있다.
<input ref={(ref) => this.input=ref} /> 과 같은 형식으로 ref를 설정할 수 있다. Ref 라는 콜백함수를 props로 전달한다. 이를 통해 input 이라는 변수명을 가진 ref 가 생성된다.
버튼을 클릭 했을 때 input에 focus를 주도록 할 것이다. 이를 위해 input 태그를 ref로 지정하고자 한다.
import React from "react";
import './validation.css'
class Validation extends React.Component {
state = {
password: '',
clicked: false,
validated: false
}
handleChange = e => {
this.setState({password: e.target.value})
}
handleButtonClick = () => {
this.setState({
clicked: true,
validated: this.state.password === '0000'
})
}
render() {
return (
<div>
<input
type="text"
onChange={this.handleChange}
className={this.state.clicked ? (this.state.validated ? 'success' : 'failure') : ''}
ref={ref => this.input=ref}
/>
<button onClick={this.handleButtonClick}>login</button>
</div>
)
}
}
export default Validation
현재는 focus 되지 않았다. 하지만 ref로 input 태그를 지정했기 때문에 직접 접근해 login 클릭 시 focus 효과가 발동되도록 코드를 수정할 수 있다.
handleButtonClick = () => {
this.setState({
clicked: true,
validated: this.state.password === '0000'
})
// ref에서 지정한 이름이 input 이다.
this.input.focus()
}
ref는 DOM에 달 수 있지만 컴포넌트에도 달 수 있다. 컴포넌트에 ref를 달게 되면 컴포넌트에 있는 내부 매서드 및 멤버 변수들에도 접근할 수 있다.
import React from "react";
class ScrollBox extends React.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

다음과 같은 스크롤 컴포넌트를 만들어 보았다. 해당 컴포넌트에 다음과 같이 높이를 계산해 바닥으로 스크롤을 이동하는 매서드를 만들 수 있다. box 는 <div ref={ref => this.box=ref}> 와 같이 ref를 설정해 직접 접근할 수 있다.
scrollToBottom = () => {
const { scrollHeight, clientHeight } = this.box
this.box.scrollTop = scrollHeight - clientHeight
}
app.jsimport 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()}>go bottom</button>
</div>
)
}
}
export default App;
컴포넌트를 ref로 설정하고, 이를 받아 버튼에 클릭 이벤트를 붙일 때 컴포넌트에 접근해 방금 만든 scrollToBottom 를 사용할수 있다.
class 컴포넌트 말고 함수형 컴포넌트를 사용할 때 상태관리, lifecycle관리 등을 활용하기 위해 hook을 사용한다. Ref 역시 함수형 컴포넌트에서 사용할 때 useRef 를 사용해 쉽게 ref를 지정할 수 있다.
const Average() => {
const inputEl = useRef(null)
...
const onInsert = useCallback(() => {
...
...
inputEl.current.focus()
}, [...])
return (
<input value={num} onChange={onChange} ref={inputEl} type="text"/>
<button onClick={onInsert}>submit</button>
)
}
버튼 클릭 시 지정된 ref에 focus 효과를 줄 수 있다. 콜백 함수를 사용해 ref를 지정했을 때와 달리 current를 통해 해당 ref에 접근할 수 있다.