html
과 js
를 사용할 때는 특정DOM
선택해야 하는 상황에 document.getElementbyId()
querySelector()
같은 DOM selector을 사용해서 선택함.
react
를 사용하는 프로젝트에서도 가끔씩 DOM
을 직접 선택해야 하는 상황 발생할 수 있다.
ex)
-> 특정 엘리먼트 크기나 위치 가져올 때,
-> 스크롤 바 위치를 가져오거나 설정해야 할 때,
-> focus
를 설정해줘야 할 때
-> 특정 라이브러리 사용할 때 등등
특정 DOM
선택할 때 리엑트에서 ref
를 사용한다.
-> 함수형 컴포넌트에서는 useRef
라는 hook
함수 사용.
-> 클래스형 컴포넌트에서는 React.createRef()
or 콜백 함수 사용.
import React, {useState, useRef} from "react";
import React, {useState, useRef} from "react";
function InputSample(){
const [inputs, setInputs] =useState({
name: '',
nickname:'',
});
const nameInput = useRef();
const {name, nickname} = inputs;
const onChange =(e)=>{
const {name, value} =e.target; // e.target에서 name, value 추출 (필수는 아님. e.target두번쓰기 싫어서),
setInputs({
// 새로운 객체 설정
...inputs,
[name]: value, // 여기서 name값은 name이 될 수도 있고, nickname이 될 수도 있음.
});
} ;
const onReset =()=>{
setInputs({
name: '',
nickname:'',
});
nameInput.current.focus();
};
return(
<div>
<input
name="name"
placeholder="이름"
onChange={onChange}
value={name}
ref={nameInput}
/>
<input
name="nickname"
placeholder="닉네임"
onChange={onChange }
value={nickname}
/>
<button onClick={onReset}>초기화</button> {/* 버튼 누르면 초기화 됨. */}
<div>
<b>값 :</b>
{name} ({nickname})
</div>
</div>
)
}
export default InputSample;
📍
const nameInput = useRef(); const {name, nickname} = inputs; // 비구조화 할당을 통해 name, nickname 추출
useRef
호출해서nameInput
이라는 객체 생성.
📍
return( <div> <input name="name" placeholder="이름" onChange={onChange} value={name} ref={nameInput} /> <input name="nickname" placeholder="닉네임" onChange={onChange } value={nickname} /> <button onClick={onReset}>초기화</button> {/* 버튼 누르면 초기화 됨. */} <div> <b>값 :</b> {name} ({nickname}) </div> </div> )
useRef()
로 만든 객체(nameInput
)를ref
라는 값으로 원하는DOM
에다가 설정.- 선택하고 싶은
DOM
에다가 객체를 넣어줌.
(ref={nameInput}
설정. )
📍
DOM
에 접근하기const onReset =()=>{ setInputs({ name: '', nickname:'', }); nameInput.current.focus(); };
- 해당
DOM
을 선택하고 싶을 때 :우리가 만든ref객체(nameInput).current.원하는 작업
->nameInput.current.focus();
current
가DOM
을 가리키게 됨.DOM API
중focus
라는 함수 사용.
-> 초기화 눌러 보면 이름에 포커스가 잡힘.
-> 초기화 버튼 누르면 focus가 초기화 버튼에 있지 않고 이름으로 가게 됨!
컴포넌트 내부에서 let
키워드로 어떤 변수 선언한다면, 다음 리렌더링 될 때는 그 변수 값이 초기화가 된다.
만약 계속 값을 유지하고 싶은 값을 관리하려면 uesState
를 사용해야 한다.
uesState
같은 경우는 상태를 바꾸게 되면 컴포넌트가 리렌더링 된다.
하지만 값을 바꿨을 때 굳이 리렌더링이 필요 없는 값을 관리할 때도 있다.
-> 이때 useRef
를 사용하면 됨!
useRef
는 이전에 특정 DOM
을 선택해야 해서ref
를 사용해야 할 때 useRef
라는 hook
을 사용하고, 그 외에도 컴포넌트가 리렌더링 될 때 마다 계속 기억할 수 있는 어떠한 값을 관리할 때 사용한다.
setTimeout
, setInterval
을 통해서 만들어진 id
scroll
위치 알고 있어야 할 때...useRef
로 관리하는 변수는 값이 바뀐다고 해서 컴포넌트가 리렌더링되지 않는다.
리액트 컴포넌트에서의 상태는 상태를 바꾸는 함수를 호출하고 나서 그 다음 렌더링 이후로 업데이트 된 상태를 조회 할 수 있는 반면, useRef
로 관리하고 있는 변수는 설정 후 바로 조회 할 수 있다.
import React,{useRef} from 'react';
import UserList from './UserList';
function App(){
const users =[
{
id:1,
username: 'gyomni',
email: 'hi1@gmail.com'
},
{
id:2,
username: 'joy',
email: 'hi2@gmail.com'
},
{
id:3,
username: 'zoe',
email: 'hi3@gmail.com'
}
];
const nextId = useRef(4);
const onCreate=()=>{
console.log(nextId.current); // 4
nextId.current+=1; // 여기서 리렌더링 되도 컴포넌트 값이 바뀌진 않음.
}
return (
<UserList users={users}/>
)
}
export default App;
nextId
를 useRef
로 관리해주는 이유는 (4)
값이 바뀐다고 해서 컴포넌트가 리랜더링 될 필요가 없기 때문이다.학습 : 벨로퍼트와 함께 하는 모던 리엑트