일반 HTML에서 DOM 요소에 이름을 달때는 id를 사용합니다.
DOM 요소의 id
<div id="my-element></div>
이렇게 HTML에서 id를 사용하여 DOM에 이름을 다는 것처럼 리액트 프로젝트 내부에서 DOM에 이름을 다는 방법이 ref(reference) 개념입니다.
"DOM을 꼭 직접적으로 건드려야 할 때"
클래스형 컴포넌트에서 ref를 사용하는 방법을 알아보겠습니다.
1. ValidationSample 컴포넌트 만들기
2. input에 ref달기
3. 버튼을 누를 때마다 input에 포커스 주기
src 디렉터리 안에 ValidationSample.css와 ValidationSample.js파일을 만듭니다.
ValidationSample.css
.success {
background-color: lightgreen;
}
.failure {
background-color: lightcoral;
}
ValidationSample.js
import { Component } from "react";
import "./ValidationSample.css";
class ValidationSample extends 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="password"
value={this.state.password}
onChange={this.handleChange}
className={
this.state.clicked
? this.state.validated
? "success"
: "failure"
: ""
}
/>
<button onClick={this.handleButtonClick}>검증하기</button>
</div>
);
}
}
export default ValidationSample;
ref를 달고자 하는 요소에 ref라는 콜백 함수를 props로 전달해주면 됩니다.
콜백 함수 사용 예시
<input ref={(ref)=>{this.input=ref}}
리액트 v16.3부터 도입된 createRef함수를 사용할 수 있습니다.
createdRef 사용 예시
import {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;
}
컴포넌트 내부에 있는 DOM을 컴포넌트 외부에서 사용할 때 씁니다.
<MyComponent
ref={(ref)=>{this.myComponent=ref}}
/>
이렇게 하면 MyComponent 내부의 메서드 및 멤버 변수에도 접근할 수 있습니다.
ScrollBox.js
import { 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;
ScrollBox.js
import { Component } from "react";
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
style={style}
ref={(ref) => {
this.box = ref;
}}
>
<div style={innerStyle} />
</div>
);
}
}
export default ScrollBox;
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>
);
}
}
export default App;
리액트를 다루는 기술 [개정판] (김민준, 길벗출판사) 책을 참고하였습니다.