일반 html에서 DOM 요소에 이름 달 때 id 사용
<div id = "my_element"></div>
요소에 id를 달면 css, js 에서 해당 id 갖고있는 요소 찾아서 작업 가능
리액트 컴포넌트 안에서도 id 사용할수는 있지만 권장 X
html에서 id는 유일해야 하는데 컴포넌트 여러번 사용한다고 할 때 중복 id 가진 DOM이 여러개 생기기 때문에 잘못된 사용
ref는 전역적 X, 컴포넌트 내부에서만 작동하기 때문에 이런 문제 X
but 리액트에서 이런 작업은 굳이 DOM에 접근하지 않아도 state로 구현 할 수 있다
ref를 사용하는 방법에는 두 가지가 있다.
// 앞으로 this.input은 input 요소의 DOM을 가리킴
<input ref = {(ref) => {this.input = ref}} />
ref의 이름은 자유롭게 지정 가능
// this.superman은 input 가리킴
<input ref = {(ref) => {this.superman = ref}} />
ref 이용해 ValidateSample에서 버튼 클릭 후에 자동으로 input창에 포커스 오도록
//ValidationSample.js
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(); // 버튼에 onClick 이벤트 발생하고 input에 다시 커서 포커스 주도록
// 이제 this.input이 컴포넌트 내부의 input요소 가리키고 있으니 일반 DOM 다루듯 코드 작성
// 밑에서 this.superman이라고 했다면 this.superman.focus()
}
render() {
return (
<div>
<input
ref = {(ref) => this.input = ref} // this.input이 컴포넌트 내부의 input요소를 가리키고 있음
// this.superman = ref라고 한다면
type = 'text'
value = {this.state.password}
onChange = {this.handleChange}
className = {this.state.clicked ? (this.state.validated ? 'success' : 'failure') : ''}
/>
<button onClick = {this.handleButtonClick}>검증하기</button>
</div>
)
}
}
<MyComponent ref = {(ref) => {this.MyComponent = ref}} />
// 이렇게 하면 MyComponent 내부의 메서드 및 멤버 변수에도 접근 가능
// ScrollBox.js
class ScrollBox extends Component {
// 스크롤바를 맨 밑으로 내리는 메서드
// 이 메서드는 부모 컴포넌트인 App에서 SrollBox에 ref 달면 사용 가능
scrollToBottom = () => {
// scrollTop: 세로 스크롤바 위치
// scrollHeight: 스크롤이 있는 박스 안의 div 높이 (가려진 부분까지 전체. 650)
// clientHeight: 스크롤이 있는 박스의 높이 (보여지는 부분. 300)
// 스크롤을 맨 아래까지 내리려면 scrollHeight에서 clientHeight 빼면 됨
const {scrollHeight, clientHeight} = this.box;
// 비구조화 할당 문법
// const scrollHeight = this.box.ScrollHeight;
// const clientHeight = this.box.clientHeight; 와 같은 의미
this.box.scrollTop = scrollHeight - clientHeight;
}
render() {
const style = {
border: '1px solid red',
height: '300px',
width: '300px',
overflow: 'auto',
position: 'relative'
};
const innerStyle = {
width: '100%',
height: '650px',
background: 'linear-gradient(yellow, blue)'
}
return (
<div
style = {style}
// 최상위 DOM에 ref 달기
ref = {(ref) => {this.box = ref}}>
<div style = {innerStyle} />
</div>
);
}
}
부모 컴포넌트인 App에서 ScrollBox에 ref 달고 (이름 scrollBox로)
버튼 누르면 ScrollBox의 scrollToBottom 메서드 실행
class App extends Component {
render() {
return (
// App 컴포넌트(부모)에서 ScrollBox에 ref 달고 (이름 scrollBox로)
// 버튼 누르면 ScrollBox의 scrollToBottom 메서드 실행
<div>
<ScrollBox ref = {(ref) => this.scrollBox = ref} />
<button onClick = {() => this.scrollBox.scrollToBottom()} >
맨 밑으로
</button>
</div>
)
}
}