728x90
반응형

5장 ref: DOM에 이름 달기

1. ref 사용하는 상황

특정 DOM에 작업 해야함 -> ref 사용 

=>  Q: '어떤' 작업??/ A: DOM을 꼭 직접적으로 건드려야 할 때

 

1) 예제 컴포넌트 생성


      
// ValidationSample.css
.success {
background-color: lightgreen;
}
.failure {
background-color: lightcoral;
}

      
// ValidationSample.js
import React, { Component } from 'react';
import './ValidationSample.css';
class ValidationSmaple 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;
  • input) onChange 이벤트 발생 -> handleChange  호출 -> state의 password 값 업데이트
    • className 값: 버튼 누르기 전 -> 비어 있는 문자열 전달
      / 버튼 누른 후 -> 검증 결과 -> true/ failure 값 설정 -> input 색상 (초록색 OR 빨간색)
  • button) onClick 이벤트 발생 -> handleButtonClick 호출 -> clicked 값: 참/ validated 값: 검증 결과

2) App 컴포넌트에서 예제 컴포넌트 렌더링


      
// App.js
import React, { Component } from 'react';
import ValidationSample from './ValidationSample';
class App extends Component {
render() {
return (
<ValidationSample />
);
}
}
export default App;

App 컴포넌트: 함수 컴포넌트 -> 클래스형 컴포넌트

3) DOM을 꼭 사용해야 하는 상황

state만으로 해결X 기능 -> DOM에 직접 접근 => ref 사용

  • 특정 input에 포커스 주기
  • 스크롤 박스 조작하기
  • Canvas 요소에 그림 그리기

2. ref 사용

1) 콜백 함수 ~> ref 설정


      
// callback 함수 사용 예시
<input ref={(ref) => {this.input=ref}} />

ref 달고자 하는 요소에 ref라는 콜백 함수 -> props로 전달

콜백 함수) ref 값 -> 파라미터로 전달 받음 -> 함수 내부에서 컴포넌트의 멤버 변수로 설정

2) createRef ~> ref 설정

리액트 v16.3부터 도입


      
// createRef 사용 예시
import React, { Component } from 'react';
class RefSmaple extends Component {
input = React.createRef();
handleFocus = () => {
this.input.current.focus();
}
render() {
return (
<div>
<input ref={this.input} />
</div>
);
}
}

컴포넌트 내부에서 멤버 변수로 React.createRef()를 담기 -> 해당 멤버 변수를 ref를 달고자 하는 요소에 ref props로 넣어줌

ref를 설정해 준 DOM에 접근: this.input.current 조회

ㄴvs. 콜백 함수.current 넣어주어야 함

3) 적용

① input에 ref 달기


      
// ValidationSample.js의 input 요소
(...)
<input
ref={(ref) => this.input=ref}
(...)
/>

콜백 함수 사용 -> ValidationSample 컴포넌트에 ref 달기

 

② 버튼 onClick 이벤트 코드 수정


      
// ValidationSample.js - handleButtonClick 메서드
handleButtonClick = () => {
this.setState({
clicked: true,
validated: this.state.password === '000'
});
this.input.focus();
}

버튼) onClick 이벤트 발생 -> input에 포커스

this.input이 컴포넌트 내부의 input 요소 가리킴 -> 일반 DOM 다루듯이 코드 작성

3. 컴포넌트에 ref 달기

= DOM에 ref 다는 방법

컴포넌트 내부에 있는 DOM -> 컴포넌트 외부에서 사용할 때 사용


      
<MyComponent
ref={(ref) => {this.myComponent=ref}}
/>

MyComponent 내부의 메서드 및 멤버 변수 접근 가능

= 내부의 ref에도 접근 가능 (ex. myComponent.handleClick, myComponent.input 등)

1) 컴포넌트 초기 설정

① 컴포넌트 파일 생성


      
// ScrollBox.js
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;

 

② App 컴포넌트에서 스크롤 박스 컴포넌트 렌더링


      
// App.js
import React, { Component } from 'react';
import ScrollBox from './ScrollBox;
class App extends Component {
render() {
return (
<div>
<ScrollBox />
</div>
);
}
}
export default App;

 

③ 컴포넌트에 메서드 생성


      
// ScrollBox.js
import React, { Component } from 'react';
class ScrollBox extends Component {
scrollToButtom = () => {
const { scrollHeight, clientHeight } = this.box;
/* 앞 코드에는 비구조화 할당 문법 사용
const scrollHeight = this.box.scrollHeight;
const clientHeight = this.box.clientHeight;
*/
this.box.scrollTop = scrollHeight - clientHeight;
}
render() {
(...)
}
}
export default ScrollBox;

 

④ 컴포넌트에 ref 달고 내부 메서드 사용


      
// 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 on Click={() => this.scrollBox.scrollToBotton()}>
맨 밑으로
</button>
</div>
);
}
}
export default App;

onClick = {this.scrollBox.scrollToBottom}: 문법상 오류 X

But, 컴포넌트가 처음 렌더링될 때 this.scrollBox 값: undefined -> this.scrollBox.scrollToBottom 값 읽어 오는 과정: 오류 O

=> 화살표 함수 문법 사용 -> 아예 새로운 함수 생성 -> 그 내부에서 this.scrollBox.scrollToBottom 메서드 실행

-> 버튼 누를 때(이미 한 번 렌더링 -> this.scrollBox 설정한 시점) this.scrollBox.scrollToBottom 값 읽어와서 실행: 오류 X


정리

  • 컴포넌트 내부에서 DOM에 직접 접근 -> ref 사용
  • 서로 다른 컴포넌트끼리 데이터 교류 -> ref 사용X
    ㄴ부모-자식 흐름으로 교류 -> 리덕스 OR Context API 사용

함수 컴포넌트) useRef라는 Hook 함수 사용 ~= React.createRef


출처

 

리액트를 다루는 기술 [개정판]

더북(TheBook): (주)도서출판 길벗에서 제공하는 IT 도서 열람 서비스입니다.

thebook.io

 

728x90
반응형
김앩옹