[React] 리액트를 다루는 기술 - 5장 ref: DOM에 이름 달기 정리
일반 HTML
에서 DOM
요소에 이름을 달 때는 id
를 사용한다. (<div id="my-element"></div>
) 그렇다면 리액트에서는 어떨까? 리액트에서도 id
를 사용할 수는 있으나, 컴포넌트를 여러 번 사용하는 것과 같은 경우에는 중복 id
를 가진 DOM
이 여러 개가 생기기 때문에 다른 방법을 이용해야 한다. 바로 컴포넌트 내부에서만 작동하는 ref(reference)
이다.
ref는 어떤 상황에서 사용해야 할까?
ref
는 DOM
을 꼭 직접적으로 건드려야 할 때 사용된다. 먼저 ref
가 아닌 state
를 사용해서 비밀번호 validation
을 구현해 보자.
/* ValidationSample.css */
.success {
background-color: lightgreen;
}
.failure {
background-color: lightcoral;
}
// ValidationSample.js
import React, { 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' // 비번이 맞으면 validated true
})
}
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;
가끔은 이처럼 state
만으로는 구현할 수 없는 기능들이 있다.
- 특정
input
에 포커스 주기- 스크롤 박스 조작하기
Canvas
요소에 그림 그리기 등
위와 같은 경우에는 어쩔 수 없이 DOM
에 직접 접근해야 함.
ref 사용
콜백 함수를 통한 ref 설정
ref
를 만드는 가장 기본적인 방법은 콜백 함수를 사용하는 것이다.
<input ref={(ref) => {this.input=ref}} />
이렇게 하면 앞으로 this.input
은 input
요소의 DOM
을 가리킨다. ref
의 이름은 원하는 것으로 자유롭게 지정할 수 있다. DOM
타입과 관계없이 this.superman = ref
처럼 마음대로 지정
createRef를 통한 ref 설정
리액트에 내장되어 있는 createRef
함수를 사용할 수도 있다.
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
를 만들려면 컴포넌트 내부에서 멤버 변수로 React.createRef()
를 담아 주어야 한다. 그리고 해당 멤버 변수를 ref
를 달고자 하는 요소에 ref props
로 넣어 주면 ref
설정이 완료된다.
나중에 ref
를 설정해 준 DOM
에 접근하려면 this.input.current
를 조회하면 된다. 콜백 함수를 사용할 때와 다른 점은 이처럼 뒤에 .current
를 넣어 주어야 한다는 것이다. 사실 아직까진 잘 모르겠지만 적용할 때 어떻게 쓰이는지 알겠지?
적용
위에서 state
를 사용했던 코드의 렌더링 결과를 살펴보면
input
요소를 클릭하면 포커스가 되면서 텍스트 커서가 깜빡이고,
button
요소를 클릭하면 포커스가 버튼으로 넘어가면서 input
요소의 텍스트 커서가 더 이상 보이지 않는다. 버튼을 한 번 눌렀을 때, 포커스가 다시 input
쪽으로 자동으로 넘어가도록 코드를 작성해 보자.
// ValidationSample.js
import React, { 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'
});
this.input.focus(); // input에 포커스
}
render() {
return (
<div>
<input
ref={(ref) => this.input=ref} // 콜백 함수로 ref 설정
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;
버튼을 눌렀을 때 버튼이 아닌 input
쪽으로 focus
가 자동으로 넘어간 것을 확인할 수 있다.
컴포넌트에 ref 달기
리액트에서는 컴포넌트에도 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) -> 350일 때 스크롤바 맨 아래scrollHeight
: 스크롤이 있는 박스 안의div
높이 (650)clientHeight
: 스크롤이 있는 박스의 높이 (300)
ScrollBox.js
의 컴포넌트 내부에 아래 메소드를 선언한다.
scrollToBottom = () => {
const { scrollHeight, clientHeight } = this.box;
this.box.scrollTop = scrollHeight - clientHeight;
}
다음으로 App
컴포넌트에서 ScrollBox
에 ref
를 달고 버튼을 만들어 누르면, ScrollBox
컴포넌트의 scrollToBottom
메소드를 실행하도록 코드를 작성한다.
// App.js
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;
💡 주의할 점
문법상으로는onClick = {this.scrollBox.scrollBottom}
같은 형식으로 작성하는 것이 가능하다. 하지만 컴포넌트가 처음 렌더링될 때는this.scrollBox
값이undefined
이므로 화살표 함수로 아예 새로운 함수를 만들고 버튼을 누를 때this.scrollBox.scrollBottom
값을 읽어 와서 실행하므로 오류가 발생하지 않는다. (이미 한 번 렌더링을 해서this.scrollBox
를 설정한 시점)
ScrollBox
컴포넌트의 scrollToBottom
메소드를 실행되어 스크롤바가 맨 아래로 이동한 것을 확인할 수 있다.
Author And Source
이 문제에 관하여([React] 리액트를 다루는 기술 - 5장 ref: DOM에 이름 달기 정리), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@dazzlynn/React-리액트를-다루는-기술-5장-ref-DOM에-이름-달기-정리저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)