일반적인 HTML에서 DOM요소에 이름을 달 때는 id를 사용한다.
그렇다면 리액트 프로젝트 내부에서는 DOM에 이름을 어떻게 달까? =>ref
리액트 컴포넌트 안에서도 id를 사용할 수 있다고 한다. 그러나 HTML에서 DOM의 id는 유일해야 하는데, 이런 상황에서는 중복 id를 가진 DOM이 여러 개 생기므로 특수한 경우가 아니면 사용을 권장하지 않는다고 한다!!
ref는 "DOM을 직접적으로 건드려야 할 때" 사용.
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>
);
}
}
.success{
background-color:lightgreen;
}
.failure{
background-color:lightcoral;
}
앞 예제는 state를 사용하여 필요한 기능을 구현했다.
그러나 state로 불가능한 기능이 있다면?
이러한 상황에서는 DOM에 직접적으로 접근해야 하므로 ref를 사용해준다.
ref를 달아야 하는 DOM에 ref 속성을 추가할 때는 props를 설정하듯이 하면 된다. ref 값으로는 콜백 함수를 전달한다.
콜백 함수는 ref를 파라미터로 가지며, 콜백 함수 내부에서 컨포넌트의 멤버 변수에 ref를 담는 코드를 작성한다.<input ref={(ref) => {this.input=ref}}></input>
이렇게 선언해주면 this.input은 input 요소의 DOM을 가리킨다.
🧨DOM 타입과 관계없이 ref의 이름은 자유롭게 지정 가능!!
<input type="password"
ref={(ref)=>this.input=ref}
...
handleButtonClick = () =>{
this.setState({
clicked:true,
validated:this.state.password==='0000'
})
this.input.focus();
}
버튼을 누르면 포커스가 input으로 넘어가는 코드.
사용법
<MyComponent ref={(ref) => {this.myComponent=ref}} />
MyComponent 내부의 메서드 및 멤버 변수에도 접근이 가능.
myComponent.handleClick, myComponent.input 등등
<button onClick={() => this.scrollBox.scrollToBottom()}>
<button onClick={this.scrollBox.scrollToBottom()}
정리
- 컴포넌트 내부에서 DOM에 직접 접근해야 할 때 ref를 사용.
- 굳이 ref를 사용하지 않아도 되는지 고려하고 사용하기!!😀
참고 : <리액트를 다루는 기술>