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 빨간색)
- className 값: 버튼 누르기 전 -> 비어 있는 문자열 전달
- 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
출처
'Programming Language > React' 카테고리의 다른 글
[리액트를 다루는 기술] 6장 컴포넌트 반복 (0) | 2023.01.15 |
---|---|
[리액트를 다루는 기술] 4장 이벤트 핸들링 (0) | 2023.01.15 |
[리액트를 다루는 기술] 3장 컴포넌트 (0) | 2023.01.15 |
[리액트를 다루는 기술] 1장 리액트 시작/ 2장 JSX (0) | 2023.01.15 |