리액트의 ref란?
- 리액트의 ref는 리액트 내부에서 state등으로 핸들링 할 수 없는 경우, 혹은 직접적으로 DOM에 접근하여 작업을 처리하거나 핸들링하기 위하여 사용합니다.
- 간단히 설명하자면 ref는 리액트 컴포넌트의 id입니다. html 태그의 id와 같은 역할을 합니다.
- ref는 다루고자 하는 컴포넌트에 ref 속성을 assign 함으로써 사용할 수 있습니다.
- 리액트 ref가 유용하게 쓰이는 경우는 특정 input에 focus를 주는 경우, 스크롤 박스를 접근하는 경우, Canvas 요소에 그림을 그리는 경우에 유용하게 사용됩니다.
- ref를 부여하면 DOM의 여러가지 속성 값에 접근할 수 있어 리액트의 일반적인 데이터의 흐름 (props, 부모 → 자식)을 거스를 수 있기 때문에 ref 통해 다른 데이터에 접근하는 것은 지양해야 합니다.
- 만약 ref를 이러한 용도로 사용하게 된다면, 코드가 스파게티 코드가 될 수 있고 유지 보수 난이도도 올라갈 수 밖에 없게 됩니다.
ref 사용하는 방법
- ref는 컴포넌트의 종류에 따라 사용법이 서로 조금씩 다릅니다.
함수형 컴포넌트
- useRef 라는 Hook을 사용합니다.
- React.creatRef() 메서드를 통해 ref를 담을 변수를 선언합니다.
import React, { useState, useRef } from 'react'
const FuncRefComp01 = () => {
const [password, setPassword] = useState('')
const [isClicked, setIsClicked] = useState(false)
let inputEle = React.createRef()
// handleChange
const handleChange = (e) => {
setPassword(e.target.value)
}
// handleButtonClick
const handleButtonClick = () => {
setIsClicked(true)
showAlert(password)
}
const checkValidation = (password) => {
if (password === '0000') {
return true
}
return false
}
// handleKeyDown
const handleKeyDown = (e) => {
if (e.key === 'Enter') {
setIsClicked(true)
showAlert(password)
}
}
const showAlert = (password) => {
if (checkValidation(password)) {
alert('비밀번호를 잘 입력하셨습니다.')
} else {
alert('비밀번호를 다시 확인 해주세요.')
}
}
return (
<>
<div className="comp func-comp ref-comp">
<input
type="password"
value={password}
onChange={handleChange}
onKeyDown={handleKeyDown}
className={
// 클래스명에 함수를 주면, 동적으로 검사를 해준다.
// 그러나 변수를 주게 되면 동적으로 검사하지 못해
// 별도로 변수를 체크해주는 함수와 함께 쓰는 등의 문법이 필요하다.
isClicked
? checkValidation(password)
? 'success'
: 'fail'
: ''
// checkValidation(password) ? 'success' : 'fail' // 이렇게 쓰면 동적 체크 가능
}
// ref={(ref) => {
// inputEle = ref
// // 함수형 컴포넌트에서 변수를 선언했을 경우 this로 가리키면 안된다.
// }}
// 아래처럼 축약해서 사용 가능함!
ref={inputEle}
/>
<button
onClick={() => {
handleButtonClick()
inputEle.current.focus()
// ref 변수를 참조 할 때는 반드시 current 프로퍼티러 접근!
}}
>
확인
</button>
</div>
</>
)
}
export default FuncRefComp01
실제 페이지
클래스형 컴포넌트
- 클래스형 컴포넌트도 마찬가지로 React.createRef()를 통해 변수를 생성하고
- 그 변수로 접근해서 current 프로퍼티를 통해 값을 처리하는 것은 같습니다.
import React, { Component, Fragment } from 'react'
class ClassRefComp02 extends Component {
input = React.createRef()
handleFocus = () => {
this.input.current.focus()
}
scrollToBottom = () => {
const { scrollHeight, clientHeight } = this.box
this.box.scrollTop = scrollHeight - clientHeight
}
scrollToTop = () => {
this.box.scrollTop = 0
}
render() {
const style = {
border: '1px solid black',
height: '300px',
width: '90%',
overflow: 'auto',
position: 'relative',
}
const innerStyle = {
widht: '100%',
height: '650px',
background: 'background: linear-gradient(black, white);',
}
return (
<>
<div className="comp class-comp ref-comp">
<input ref={this.input} />
<button
onClick={() => {
this.handleFocus()
}}
>
포커스
</button>
<button onClick={this.scrollToTop}>스크롤 UP</button>
<button onClick={this.scrollToBottom}>스크롤 DOWN</button>
</div>
{/* 스크롤 박스! */}
<div className="comp class-comp ref-comp">
<div
style={style}
ref={(ref) => {
this.box = ref
// 별도로 변수를 선언하진 않았지만, 이런식으로 작성하면
// 자동으로 변수가 선언되 효과가 있으며 정상 작동함.
}}
>
<div style={innerStyle}></div>
</div>
</div>
</>
)
}
}
export default ClassRefComp02
실제 페이지
'프론트엔드(Front-End) > React' 카테고리의 다른 글
[REACT] 리액트의 라이프사이클(LifeCycle) (0) | 2023.01.07 |
---|---|
[REACT] 컴포넌트 요소의 반복(map, filter) (0) | 2023.01.06 |
[REACT] 리액트와 EVENT (0) | 2023.01.04 |
[REACT] 리액트의 STATE (0) | 2023.01.03 |
[REACT] 리액트의 컴포넌트(COMPONENT) (0) | 2023.01.02 |