
오늘은 ref에 대해서 공부해봅시다!
HTML에서 id를 사용하여 DOM에 이름을 다는 것 처럼 리액트 프로젝트 내부에서 DOM에 이름을 다는 방법이 있다. 바로 ref(reference의 줄임말) 개념이다.
❓ 리액트 컴포넌트 안에서 id는 사용하면 안되나?
-id를 사용할 수 있지만 특수한 경우가 아니면 사용을 권장하지는 않는다. 같은 컴포넌트를 여러 번 사용한다면 중복 id를 가진 DOM이 여러개 생기므로 잘못된 사용법이다. (HTML에서 DOM의 id는 유일해야하므로 ! )
✅ 그러나 ref는 전역적으로 작동하지 않고 컴포넌트 내부에서만 작동하기 때문에 문제가 발생하지 않는다 !
ref는 DOM을 꼭 직접적으로 건드려야 할 때 사용된다.
ValidationSample 컴포넌트 만들기->input에 ref 달기-> 버튼을 누를 때마다 input에 포커스 주기
순서로 실습을 진행해보자
ValidationSample.css와 ValidationSample.js 파일 생성
✍ example
//css
.success {
background-color: lightgreen;
}
.faliure {
background-color: lightcoral;
}
//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':'faliure'):''}
/>
<button onClick={this.handleButtonClick}>검증하기</button>
</div>
);
}
}
export default ValidationSample;
✍ example
//App.js
import { Component } from "react";
import ValidationSample from './ValidationSample';
class App extends Component{
render() {
return (
<ValidationSample/>
);
}
}
export default App;
| 콜백 함수를 통한 ref 설정 | createRef를 통한 ref 설정 |
|---|---|
| -가장 기본적인 방법 -ref를 달고자 하는 요소에 ref라는 콜백함수를 props로 전달 | -더 적은 코드로 쉽게 사용 가능 -리액트 v16.3부터 도입 (이전 버전에서는 작동하지 않음.) |
✍ example
<input ref={(ref)=>{this.input=ref}}/>
this.input은 input 요소의 DOM을 가리킴. 이를 통해 input이라는 이름의 ref 생성.this.superman=ref✍ example
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;
createRef 함수를 이용하여 ref 생성. input=React.createRef(); : 컴포넌트 내부에서 멤버 변수로 React.createRef()를 담아줌. input ref={this.input} : ref를 달고자 하는 요소에 ref props로 넣어주면 ref 설정이 완료. this.input.current.focus(); : ref를 설정한 DOM에 접근하기 위해서는 this.input.current를 조회하면 됨. 버튼을 눌렀을 때, 포커스가 다시 input 쪽으로 자동으로 넘어가도록 코드를 작성해보자.
✍ example
<input
ref={(ref)=>this.input=ref}
(...)
/>
✍ example
handleButtonClick=()=>{
this.setState({
clicked:true,
validated:this.state.password==='0000'
});
this.input.focus();
}
컴포넌트 내부에 있는 DOM을 컴포넌트 외부에서 사용할 때 컴포넌트에 ref를 단다.
✍ example
<MyComponent
ref={(ref)=>{this.myComponent=ref}}
/>
✍ example
//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;
✍ example
//App.js
import { Component } from "react";
import ScrollBox from "./ScrollBox";
class App extends Component{
render() {
return (
<ScrollBox/>
);
}
}
export default App;
✍ example
scrollToBottom=()=>{
const{scrollHeight, clientHeight}=this.box;
this.box.scrollTop=scrollHeight-clientHeight;
}
✍ example
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;
🛑주의할 점
문법상으로는 onClick={this.scrollBox.scrollBottom}으로 써도 틀린 것은 아님. 그러나 컴포넌트가 처음 렌더링 될 때에는 this.scrollBox가 undefined이므로 this.scrollBox.scrollBottom값을 읽어오는 과정에서 오류 발생. 따라서 새로운 함수를 만들고 내부에서 this.scrollBox.scrollToBottom 메서드를 실행하면 오류가 발생하지 않음.
✔ 결과 확인

컴포넌트 내부에서 DOM에 직접 접근해야 할 때는 ref를 사용한다는 것을 배우고 실습까지 진행해보았습니다. 다음 시간에는 컴포넌트의 반복에 대해서 공부해보겠습니다 🤗