[react] DOM에 이름 달기 ref
by 너나나
HTML에서 id를 사용하여 DOM에 이름을 다는 것처럼 리액트 프로젝트 내부에서 DOM에 이름을 다는 방법이 있다!! 이게 바로 ref(reference) 개념이다!!
DOM을 직접적으로 건드려야 할 때 ref를 사용해야한다.
DOM 이란
Document Object Model의 약자로 문서 객체 모델이라고 번역할 수 있다. <html>이나 <body>같은 html 문서의 태그들을 javascript가 이용할 수 있는 객체로 만들면 그것을 객체 문서라고 한다. 그러니까 웹 브라우저가 html 페이지를 인식하는 방식을 DOM이라고 하는데 개발자 도구에서 F12를 눌러서 볼 수 있는 친구들이 바로 DOM이다!!
src 디렉토리 안에 ValidationSample.css, ValidationSample.js 파일을 만들었다.
ValidationSample.css
.success {
background-color: lightgreen;
}
.failure {
background-color: lightcoral;
}
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'
})
}
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
비밀번호를 입력하고 확인 버튼을 눌렀을때 비밀번호가 0000이 맞다면 초록색으로 텍스트필드를 바꿔주고 틀렸다면 빨간색으로 바꿔주는 코드이다!!
여기서는 state를 사용해서 필요한 기능을 구현했지만, 가끔 state만으로 해결할 수 없는 기능이 있다.
- 특정 input에 포커스 주기
- 스크롤 박스 조작하기
- Canvas 요소에 그림 그리기 등
이때는 어쩔 수 없이 DOM에 직접적으로 접근해야 하는데, 이를 위해 바로 ref을 사용한다.
ref을 만드는 가장 기본적인 방법은 콜백 함수를 사용하는 것이다!! ref를 달고자 하는 요소에 ref라는 콜백 함수를 props로 전달해 주면 된다. 이 콜백 함수는 ref 값을 파라미터로 전달받는다! 그리고 함수 내부에서 파라미터로 받은 ref을 컴포넌트의 멤버 변수로 설정해준다.
<input ref={(ref) => {this.input=ref}} />
이렇게 하면 앞으로 this.input은 input 요소의 DOM을 가킨다!! ref의 이름은 원하는 것으로 자유롭게 지정할 수 있다!!
리액트에 내장되어있는 createRef 라는 함수를 사용해서 ref을 만들 수도 있다!! 이 함수를 사용해서 만들면 더 적은 코드로 쉽게 사용할 수 있다!!
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
컴포넌트 내부에서 멤버 변수로 React.createRef()을 담아주고 해당 멤버 변수를 ref을 달고자 하는 요소에 ref props로 넣어 주면 ref 설정이 완료된다. 설정한 뒤 나중에 ref을 설정해 준 DOM에 접근하려면 this.input.current를 조회하면 된다!! 콜백 함수를 사용할 때와 다른점은 뒷부분에 .current를 넣어줘야한다는 것이다!!!
그러면 아까 만들었던 ValidationSample 컴포넌트에 ref을 달아보자!!
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();
}
render() {
return (
<div>
<input
ref={(ref) => this.input=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에 커서가 깜박거리게 하기 위해서 handleButtonClick에 this.input.focus();를 추가하고 input에 ref을 달아줬따!!
리액트에서는 컴포넌트에도 ref을 달 수 있다. 이 방법은 주로 컴포넌트 내부에 있는 DOM을 컴포넌트 외부에서 사용할 때 쓴다!! 컴포넌트에서 ref를 다는 방법은 DOM에 ref를 다는 방법과 똑같다!!
<MyComponent
ref={(ref) => {this.myComponent=ref}}
/>
이렇게 하면 MyComponent 내부의 메서드 및 멤버 변수에도 접근할 수 있다!! 즉 내부의 ref에도 접근할 수 있다.
스크롤 박스가 있는 컴포넌트를 하나 만들고, 스크롤바를 아래로 내리는 작업을 부모 컴포넌트에서 실행해보자!!
ScrollBox라는 컴포넌트 파일을 만들었다!!
import React, { Component } from 'react';
class ScrollBox extends Component {
render() {
const style = {
border: '1px solid balck',
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로 가서 ScrollBox 컴포넌트를 렌더링해주자!!
import React, { Component } from "react";
import './App.css';
import ScrollBox from "./ScrollBox";
class App extends Component {
render() {
return (
<div>
<ScrollBox />
</div>
)
}
}
export default App
그러면 이렇게 스크롤 박스가 잘 렌더링된다!!
컴포넌트에 스크로바를 맨 아래쪽으로 내리는 메서드를 만들자!!
자바스크립트로 스크롤바를 내릴 때는 DOM 노드가 가진 다음 값들을 사용한다.
- scrollTop : 세로 스크롤바 위치(여기서는 0~350)
- scrollHeight : 스크롤이 있는 박스 안의 div 높이(여기서는 650)
- clientHeight : 스크롤이 있는 박스의 높이(여기서는 300)
스크롤바를 맨 아래쪽으로 내리려면 scrollHeight에서 clientHeight 높이를 빼면 된다.
ScrollBox.js 의 render함수 외부에
scrollToBottom = () => {
const { scrollHeight, clientHeight } = this.box;
this.box.scrollTop = scrollHeight - clientHeight;
}
이 메서드를 추가해줬다!!
이렇게 만든 메서드는 부모 컴포넌트인 App 컴포넌트에서 ScrollBox에 ref를 달면 사용할 수 있다!!
그럼 App 컴포넌트에서 ScrollBox에 ref을 달고 버튼을 누르면 ScrollBox 컴포넌트의 scrollToBottom 메서드를 실행하도록 코드를 작성해보자!!
import React, { Component } from "react";
import './App.css';
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
이러고 실행해보면
잘 작동하는것을 볼 수 있다!!
참고 자료
「리액트를 다루는 기술 - 김민준」
'study > react (2021 여름방학)' 카테고리의 다른 글
[react] 라이프사이클 메서드 (0) | 2021.07.24 |
---|---|
[react] 컴포넌트 반복 (0) | 2021.07.18 |
[react] 이벤트 핸들링 (0) | 2021.07.17 |
[react] props, state (0) | 2021.07.13 |
[react] 리액트 정리 - 1 (0) | 2021.07.11 |
블로그의 정보
공부 기록
너나나