프론트엔드/React
useRef
alswlfl
2022. 11. 16. 22:38
useRef
useRef로 특정 DOM 선택하기
★ DOM(문서 객체 모델): XML이나 HTML문서에 접근하기 위한 일종의 인터페이스, 이 객체 모델은 문서 내의 모든 요소를 정의하고, 각각의 요소에 접근하는 방법 제공
- 자바스크립트에서는 특정 DOM을 선택해야 하는 상황에 getElementById, querySelector 같은 DOM. Selector 함수를 사용해서 DOM 선택
- 리액트에서는 ref사용
- 함수형 컴포넌트: useRef라는 Hook 함수 사용
- 클래스형 컴포넌트: 콜백 함수 사용하거나 React.createRef라는 함수 사용
useRef사용 이유
- 값 저장: 현재 저장하고 싶은 값을 리렌더링 없이 저장
- DOM 참조: DOM참조가능, 현재 DOM에서 element의 scroll위치, image의 size 등을 참조할 수 있다.
- useState로 관리하게 되면, 리렌더링이 계속 발생하므로 비효율적이고, 코드 구현하기 어려워짐
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 { value, name } = e.target;//우선 e.target에서 name과 value를 추출
setInputs({
...inputs,//기존의 input객체 복사한 뒤
[name]: value,//name키를 가진 값을 value로 설정
});
};
const onReset = () => {
setInputs({
name: "",
nickname: "",
});
nameInput.current.focus();//onReset함수에서 input에 포커스하는 focus() DOM API
};
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;
- useRef()를 사용하여 Ref 객체를 만들고, 이 객체를 우리가 선택하고 싶은 DOM에 ref값으로 설정해주어야 함
- Ref객체의 .current값은 우리가 원하는 DOM 을 가리키게 됨
배열 렌더링
import React from "react";
function User({ user }) {
return (
<div>
<b>{user.username}</b> <span>({user.email})</span>
</div>
);
}
function UserList() {
const users = [
{ id: 1, username: "velopert", email: "public.velopert@gmail.com" },
{ id: 2, username: "tester", email: "tester@example.com" },
{ id: 3, username: "liz", email: "liz@example.com" },
];
return (
<div>
<User user={users[0]} />
<User user={users[1]} />
<User user={users[2]} />
</div>
);
}
export default UserList;
- 배열이 고정적이면 괜찮지만, 배열 인덱스 하나하나 조회하며 렌더링하는 방법은 동적인 배열 렌더링 못함
동적인 배열 렌더링 방법
: 자바스크립트 배열의 내장함수 map() 사용, 이 함수를 사용하여 일반 데이터 배열을 리액트 엘리먼트로 이루어진 배열로 변환
⭐️ map: 배열 안의 각 원소를 변환하여 새로운 배열을 만들 때 사용
- 리액트에서 배열 렌더링 할 때, key라는 props 설정해야함
►key 값은 각 원소들마다 가지고 있는 고유값으로 설정
import React from "react";
function User({ user }) {
return (
<div>
<b>{user.username}</b> <span>({user.email})</span>
</div>
);
}
function UserList() {
const users = [
{ id: 1, username: "velopert", email: "public.velopert@gmail.com" },
{ id: 2, username: "tester", email: "tester@example.com" },
{ id: 3, username: "liz", email: "liz@example.com" },
];
return (
<div>
{users.map((user) => (
<User user={user} key={user.id} />
))}
</div>
);
}
export default UserList;
- 배열을 렌더링 할 때 key 설정하지 않으면 기본적으로 배열의 index값을 key로 사용하고, 경고 메시지가 뜸
※ 배열 안의 원소가 가지고 있는 고유한 값이 없다면 map()함수를 사용할 때 설정하는 콜백함수의 두번째 파라미터 index를 key로 사용
return (
<div>
{users.map((user, index) => (
<User user={user} key={index} />
))}
</div>
);
key의 존재유무에 따른 업데이트 방식
key가 없을 때,
const array=['a','b','c','d'];
array.map(item=><div>{item}</div>);
Q. b와 c 사이에 z를 삽입하는 경우
A. 리렌더링 시, <div>b</div>와 <div>c</div>사이에 새로운 div태그를 삽입하는 것이 아니라, 기존의 c가 z로 바뀌고, d는 c로 바뀌고, 맨 마지막에 d가 새로 삽입
Q. a를 제거하는 경우
A. 기존의 a가 b로 바뀌고, b는 z로 바뀌고, z는 c로 바뀌고, c는 d로 바뀌고, 맨 마지막에 있는 d제거
즉, key가 존재하지 않을 때, 기존에 있던 값을 건들이면서 업데이트
key가 있을 때,
[
{
id: 0,
text: 'a'
},
{
id: 1,
text: 'b'
},
{
id: 2,
text: 'c'
},
{
id: 3,
text: 'd'
}
];
array.map(item => <div key={item.id}>{item.text}</div>);
key가 있을 때, 수정되지 않는 기존의 값은 그대로 두고 원하는 곳에 내용을 삽입하거나 삭제
- 배열 안에 중복되는 key가 있을 때, 렌더링 시 오류메시지가 콘솔에 나타나 업데이터가 제대로 이루어지지 않음
useRef로 컴포넌트 안의 변수 만들기
useRef의 용도
- DOM 선택
- 컴포넌트 안에서 조회 및 수정 할 수 있는 변수 관리
- setTimeout, setInterval을 통해서 만들어진 id
- 외부 라이브러리를 사용하여 생성된 인스턴스
- scroll위치 ▸ [react] scroll event (테스트)
import React from "react";
function User({ user }) {
return (
<div>
<b>{user.username}</b> <span>({user.email})</span>
</div>
);
}
function UserList({ users }) {
return (
<div>
{users.map((user) => (
<User user={user} key={user.id} />
))}
</div>
);
}
export default UserList;
import React, { useRef } from "react";
import UserList from "./UserList";
function App() {
const users = [
{
id: 1,
username: "velopert",
email: "public.velopert@gmail.com",
},
{
id: 2,
username: "tester",
email: "tester@example.com",
},
{
id: 3,
username: "liz",
email: "liz@example.com",
},
];
const nextId = useRef(4); //useRef() 사용할 때 파라미터 넣어주면, 이 값이 .current값의 기본값이 됨
const onCreate = () => {
nextId.current += 1; //값 수정 시, .current 값 수정하면 되고, 조회할 때도 .current조회하면 됨
};
return <UserList users={users} />;
}
export default App;