ref에 대하여.
※잘 이해가 안가는 혹은 헷갈리는 react의 기초문법들만 정리하는 중.
1. useRef 로 특정 DOM선택하기
html 과 JavaScript를 사용할때는 특정 DOM을 선택해야되는 상황에, getElementById또는 querySeletor같은 DOM seletor함수를 사용해서 DOM을 선택한다. 그런데 React를 사용하는 프로젝트에서도 종종 DOM을 직접적으로 선택해야되는 상황이 있을 수 있다. 그건 언제일까?
- 특정 엘리먼트의 크기나 위치
- 스크롤바 위치를 가져오거나 설정
- focus설정
- Video.js 그리고 JWPlayer.js같은 html5 video관련 라이브러리 사용 -> 특정 DOM에 라이브러리 적용
- D3.js 그리고 Chart.js 같은 그래프관련 라이프러리 -> 특정 DOM에 라이브러리 적용
등 다양한 상황에서 DOM을 선택해야 되는 상황이 있을 수 있다. 따라서 이럴때는 react에서 ref라는 것을 사용한다. 함수형 컴포넌트에서ref를 사용할때는 useRef라는 hook함수를 사용한다. 그리고 class형 컴포넌트에서는 React.createRef()를 사용한다. 또는 callback()함수로도 사용가능하다.
그런데 지금은 함수형 컴포넌트에서 사용하는 ref즉, useRef에서만 알아보자!
지금 당장 구현하고싶은것은 아래와 같다. 즉 초기화를 눌렀을때 focus를 '이름'이 있는곳에 놓고싶은것이다. 그런데 react 자체적 기능으로는 딱히할 수 있는게없다. 이럴때는 어쩔 수 없이 DOM에 직접 접근을 해야만한다.
그럼이제 DOM에 직접 접근하는 방법을 알아보자.
import React,{useState, useRef} from 'react';
function UseRef(){
const [inputs, setInputs] = useState({
name:'',
nickname:'',
})
const nameInput = useRef(); //nameInput객체 만들었다.
const {name, nickname} = inputs;
const onChange = (e)=>{
const {name, value} = e.target;
setInputs({
...inputs,
[name]:value,
});
}
const onReset = () =>{
setInputs({
name:'',
nickname:''
})
//nameInput객체 .current 값이 현재 선택하고 싶은 DOM을 가르키고있으니까, 뒤로 원하는 작업을 해준다.
nameInput.current.focus(); //current가 dom을 가르키게된다.
}
return(
<div>
<input
name="name"
placeholder="이름"
onChange={onChange}
value={name}
ref={nameInput} //ref속성 추가 - 원하는 DOM에다가 설정한다.
/>
<input
name="nickname"
placeholder="닉네임"
onChange={onChange}
value={nickname}
/>
<button onClick={onReset}>초기화</button>
<div>
<b>값:</b>
{name}({nickname})
</div>
</div>
)
}
export default UseRef;
1. useRef 로 컴포넌트 안의 변수만들기
- useRef는 DOM을 선택하는 말고도 랜더링과 전혀 관계없는 변수같은 것을 관리하게될때도 사용할 수가 있다.
- 여기서 말하는 변수는 예를들어 컴포넌트 내부에서 let키워드를 사용해서 어떤 변수를 선언한다고 가정해보겠다. 그렇게하면 다음 reRandering될때는 그 변수값은 초기화된다. 만약에 계속 유지하고싶은 어떤 값을 관리하려면 useState를 사용해야되는데, 이는 상태를 바꾸게되면 컴포넌트가 reRandering이된다. 하지만 어떤 값을 바꿨을 때 굳이 reRandering할 필요없는 그런 값을 관리할 때도 있다. 그럴경우 useRef를 hook을 사용한다. useRef는 특정 DOM을 선택해야될 때 ref를 사용해야될때 사용했다. 그런데 이것 외에도 컴포넌트가 reRandering 될 때마다 계속 기억할 수 있는 어떤 값을 관리할 때도 사용할 수가 있다.
- 주로 setTimeout, setInterval를 사용했을 때 주어지는 id값을 기억해야 될 때도 사용
- 외부 라이브러리를 사용해서 생성된 인스턴스를 담을때도 사용, 아니면 scroll위치를 알고 있어야 될때도 사용 등 다양하다.
- point : useRef로 관리하는 값은 바껴도 reRandering이 되지않는다.
실습 : useRef를 사용해서 변수를 관리해보자
용도 : 배열에 새 항목을 추가 할 것인데, 새 항목에서 사용할 고유id값을 관리하기 위해서 사용하는 것이다.
그런데 이 작업을 하기전에 해야 할 일있다. 이전 위의 코드를 변형해보겠다.
users list를 pops로 받아오겠다.
//userList.js
import React from 'react';
//props로 user값을 받아올 것이다.
function User({user}){
console.log(user);
return(
<div>
<b>{user.username}</b><span>{user.email}</span>
</div>
);
}
function UserList({users}){ //porps로 받아온 users
//array를 랜더링하는 jsx를 작성
return(
<div>
{
users.map(
user=>(<User user={user} key = {user.id}/>)
)
}
</div>
)
}
export default UserList;
//App.js
import React,{useRef} from 'react';
import UserList from './components/userList';
function App() {
const users = [
{
id:1,
username:'velopert',
email:'public.thxjek@gmail.com'
},
{
id:2,
username:'tester',
email:'tester@example.com'
},
{
id:3,
username:'liz',
email:'liz@example.com'
}
];
//useRef어떤 변수를 계속 기억하고싶을 때 이와같이 사용된다.
//이값은 컴포넌트가 리랜더링되도 계속 기억한다.
const nextId = useRef(4);
const onCreate = ()=>{
console.log(nextId.current); //4
nextId.current +=1; //즉, 이 값이 바뀐다고 컴포넌트가 리랜더링 되지 않는다.
}
return (
<UserList users={users}/>
);
}
export default App;
참고자료 :
최근댓글