Preview
- HTML에서 id 를 사용해 이름을 다는 것처럼 React에서는 ref(reference)를 이용해 DOM 에 이름을 붙여준다
- id를 사용할 경우 컴포넌트가 반복될 때, 고유해야할 id 값이 여러번 사용될 수 있으므로 ref를 사용하는 걸 권장한다
- ref는 컴포넌트 내부에서만 작동한다
ref
- DOM을 직접적으로 건드려야 할 때 사용한다
- 비밀번호 검증 페이지 만들기 실습
- ValidationSample 컴포넌트 만들기
- input에 ref 달기
- 버튼을 누를 때마다 input에 포커스 주기
1. 예제 컴포넌트 생성
- input에서 onChange 이벤트가 발생하면 handleChange 호출하여 state의 password 값을 업데이트
- button에서 onClick 이벤트가 발생하면 handleButtonClick 을 호출하여 clicked 값을 true로 설정, validated 검증
- className 값은 버튼을 누르기 전에는 비어있는 문자열 전달, 버튼을 누른 후에는 검증 결과에 따라 sucess 또는 faulure 반환, 결과에 따라 색상 변경
- 이전에 배운 onKeyDown 이벤트 핸들링 추가
// 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',
});
};
handleKeyPress = (e) => {
if (e.key === 'Enter') {
this.handleButtonClick();
}
};
render() {
return (
<div>
<input
type="password"
value={this.state.password}
onChange={this.handleChange}
className={
this.state.clicked
? this.state.validated
? 'sucess'
: 'failure'
: ''
}
onKeyDown={this.handleKeyPress}
/>
<button onClick={this.handleButtonClick}>검증하기</button>
</div>
);
}
}
export default ValidationSample;
/* ValidationSample.css */
.sucess {
background-color: lightgreen;
}
.failure {
background-color: lightcoral;
}
2. App 컴포넌트에 렌더링
//App.js
import React, { Component } from 'react';
import ValidationSample from './ValidationSample';
class App extends Component {
render() {
return (
<div>
<ValidationSample />
</div>
);
}
}
export default App;
3. 결과
4. DOM을 꼭 사용해야 하는 상황
- state만으로는 해결하기 어려운 기능이 있을 땐 ref를 사용한다
- 특정 input에 포커스 주기
- 스크롤 박스 조작하기
- Canvas 요소에 그림 그리기 등
ref 사용하기
1. 콜백 함수를 통한 ref 설정
- ref를 달고자 하는 요소에 ref 라는 콜백 함수를 props 해주기
- 콜백 함수는 ref 값을 파라미터로 전달 받고, 함수 내부에서 컴포넌트의 멤버 변수로 설정
<input ref = {(ref) => {this.input=ref}} />
- 이렇게 하면 this.input은 input 요소의 DOM을 가리킴
2. 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;
- 사용을 위해선 컴포넌트 내부에서 멤버 변수로 React.createRef()를 먼저 담아줘야 함
- 해당 변수를 ref를 달고자 하는 요소에 ref props로 넣어주면 설정 완료
- 설정한 뒤 ref를 설정해 준 DOM에 접근하려면 this.input.current로 조회
3. 검증하기를 누른 후에도 커서가 input에 있도록 설정하기
3-1. input에 ref 달기
(...)
<input
ref={(ref) => (this.input = ref)}
(...)
/>
3-2. 버튼 onClick 이벤트 코드 수정
handleButtonClick = () => {
this.setState({
clicked: true,
validated: this.state.password === '0000',
});
this.input.focus();
};
컴포넌트에 ref 사용하기
- 컴포넌트 내부에 있는 DOM을 컴포넌트 외부에서 쓸 때 사용
- DOM에 ref 다는 방법과 같음
사용법
<MyComponent
ref = {(ref) => {this.myComponent=ref}}
/>
- 이렇게 하면 MyComponent 내부의 메서드 및 멤버 변수에 접근 가능
- 즉 내부의 ref에 접근 가능(myComponent.handleClick, myComponent.input)
스크롤 박스 실습
진행 순서
- ScrollBox 컴포넌트 만들기
- 컴포넌트에 ref 달기
- ref를 이용하여 컴포넌트 내부 메서드 호출하기
1. 컴포넌트 초기 설정
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에도 등록하기
- 결과
2. 컴포넌트에 메서드 생성
- 컴포넌트에 스크롤바를 맨 아래쪽으로 내리는 메서드 생성
- scrollTop : 세로 스크롤바 위치(0~350)
- scrollHeight : 스크롤이 있는 박스 안의 div 높이(650)
- clientHeight : 스크롤이 있는 박스의 높이(300)
- 스크롤바를 맨 아래쪽으로 내리려면 scrollHeight - clientHeight
// ScrollBox.js
import React, { Component } from 'react';
class ScrollBox extends Component {
scrollToBottom = () => {
const { scrollHeight, clientHeight } = this.box;
this.box.scrollTop = scrollHeight - clientHeight;
};
render() {
(...)
}
export default ScrollBox;
3. 컴포넌트에 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 onClick={() => this.scrollBox.scrollToBottom()}>
맨 밑으로
</button>
</div>
);
}
}
export default App;
- 컴포넌트가 처음 렌더링 될 때 단순히 `onClick={this.scrollBox.scrollToBottom}`으로 적으면 this.scrollBox 값이 undefined이므로 오류가 발생할 수 있음
- 화살표 함수를 만들면 이미 한번 렌더링되면서 this.scrollBox가 설정되므로, 버튼을 누를 때 오류가 생기지 않음
- "첫페이지 렌더링 + 버튼 클릭" 을 "첫페이지 렌더링 -> 버튼 클릭" 으로 동작하게 하는 것
ref 사용 주의사항
- 서로 다른 컴포넌트끼리 데이터를 교류할 때 ref 를 사용하면 나중에 꼬여서 유지보수가 어려워짐
- 부모 - 자식 흐름으로 교류해야 함
'개발새발개발 > React' 카테고리의 다른 글
React - 라이프사이클 메서드 카테고리와 종류 (0) | 2025.01.01 |
---|---|
React - 컴포넌트 반복(map, callback, key, list, 값 추가 삭제) (1) | 2024.12.30 |
React 이벤트 핸들링 (1) | 2024.12.28 |
React state, 클래스형 컴포넌트와 함수형 컴포넌트에서의 state와 주의사항 (0) | 2024.12.25 |
React 컴포넌트(Component), 화살표 함수, Snippet (1) | 2024.12.24 |
댓글