https://react.vlpt.us/basic/10-useRef.html
10. useRef 로 특정 DOM 선택하기 · GitBook
10. useRef 로 특정 DOM 선택하기 JavaScript 를 사용 할 때에는, 우리가 특정 DOM 을 선택해야 하는 상황에 getElementById, querySelector 같은 DOM Selector 함수를 사용해서 DOM 을 선택합니다. 리액트를 사용하는
react.vlpt.us
useRef로 특정 DOM 선택하기
리액트에서 DOM을 선택할 때 ref 라는 것을 사용한다.
React에서 state로만 해결할 수 없고, DOM을 반드시 직접 건드려야 할 때 사용하게 된다.
ex ) 특정 input에 focus 주기, 스크롤 박스 조작, Canvas 요소에 그림 그리기 등..
함수형 컴포넌트에서 ref를 사용할 때는 useRef라는 Hook 함수를 사용한다.
useRef는 리렌더링 하지 않는다. 컴포넌트의 속성만 조회&수정한다.
앞서 작성했던 Input 글에서 초기화 버튼을 눌렀을 때
이름 input에 포커스가 잡히도록 useRef를 사용해서 기능을 구현해보자
App.js
import React from "react";
import InputSample from "./InputSample";
function App() {
return <InputSample />;
}
export default App;
InputSample.js
import React, { useRef, useState } from "react";
function InputSample() {
const [inputs, setInputs] = useState({
name: " ",
nickname: " ",
});
const nameInput = useRef(); // Ref 객체 생성
const { name, nickname } = inputs;
const onChange = (e) => {
const { name, value } = e.target;
setInputs({
...inputs,
[name]: value,
});
};
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;
배열 렌더링하기
// map 함수
let arr = [3, 4, 5, 6];
let modifiedArr = arr.map(function(element){
return element *3;
});
console.log(modifiedArr); // [9, 12, 15, 18]
배열이 고정적이면 상관없지만, 배열의 인덱스를 하나하나 조회해가면서 렌더링하는 방법은
동적인 배열을 렌더링하지 못한다.
동적인 배열을 렌더링 할 때는 js 배열의 내장함수 map()을 사용한다.
map() 함수는 배열 안에 있는 각 원소를 변환하여 새로운 배열을 만들어준다.
리액트에서 동적 배열을 렌더링해야 할 때는 이 함수를 이용해
일반 데이터 배열을 리액트 엘리먼트로 이루어진 배열로 변환해주면 된다.
App.js
import React from "react";
import UserList from "./UserList";
function App() {
return <UserList />;
}
export default App;
UserList.js
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: "daramG",
email: "daramG@daram.com",
},
{
id: 2,
username: "pinkbean",
email: "pinkbean@daram.com",
},
{
id: 3,
username: "raichu",
email: "raichu@daram.com",
},
];
// user = {user}
// 앞의 user : User 컴포넌트에 들어가는 user 인자
// 뒤의 {user} : users 배열의 각 원소값
// +
// 배열 안의 원소가 가지고 있는 고유한 값이 없다면 key = {index}
// 각 고유 원소에 key가 있어야만 배열이 업데이트 될 때 효율적으로 렌더링된다.
return (
<div>
{users.map((user) => (
<User user={user} key={user.id} />
))}
</div>
);
}
export default UserList;
↓ (배열을 App 에서 선언하고 UserList에게 props로 전달하는 코드로 변경)
App.js
import React from "react";
import UserList from "./UserList";
function App() {
const users = [
{
id: 1,
username: "daramG",
email: "daramG@daram.com",
},
{
id: 2,
username: "pinkbean",
email: "pinkbean@daram.com",
},
{
id: 3,
username: "raichu",
email: "raichu@daram.com",
},
];
return <UserList users={users} />;
}
export default App;
UserList.js
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;
실행결과 )
useRef 로 컴포넌트 안의 변수 만들기
// useRef()는 언제 사용하는가
useRef Hook은 DOM을 선택하는 것 외에도, 컴포넌트 안에서 조회 및 수정할 수 있는 변수를 관리할 수도 있다.
useRef 로 관리하는 변수는 값이 바뀐다고 해서 컴포넌트가 리렌더링되지 않는다.
다음과 같은 값을 관리할 수 있다.
- setTimeout, setInterval 을 통해 만들어진 id
- 외부 라이브러리를 사용해 생성된 인스턴스
- scroll 위치
App에 useRef()를 사용하여 nextId 라는 변수 생성
App.js
import React, { useRef } from "react";
import UserList from "./UserList";
function App() {
const users = [
{
id: 1,
username: "daramG",
email: "daramG@daram.com",
},
{
id: 2,
username: "pinkbean",
email: "pinkbean@daram.com",
},
{
id: 3,
username: "raichu",
email: "raichu@daram.com",
},
];
// useRef() 파라타미터로 다음 id가 될 숫자 4를 넣어준다.
// 파라미터 값을 넣어주면 해당 값이 변수의 current 값이 된다.
// nextId 변수를 수정하거나 조회려면 .current 값을 수정하거나 조회한다.
const nextId = useRef(4);
const onCreate = () => {
// 배열 항목 추가, 나중에 구현
}
return <UserList users={users} />;
}
export default App;
배열에 항목 추가하기
App.js
import React, { useRef, useState } from "react";
import UserList from "./UserList";
import CreateUser from "./CreateUser";
function App() {
const [inputs, setInputs] = useState({
username: "",
email: "",
});
const { username, email } = inputs;
const onChange = (e) => {
const { name, value } = e.target;
setInputs({
...inputs,
[name]: value, // name 키를 가진 값을 value로 변경
});
};
const [users, setUsers] = useState([
{
id: 1,
username: "daramG",
email: "daramG@daram.com",
},
{
id: 2,
username: "pinkbean",
email: "pinkbean@daram.com",
},
{
id: 3,
username: "raichu",
email: "raichu@daram.com",
},
]);
// useRef() 파라타미터로 다음 id가 될 숫자 4를 넣어준다.
// 파라미터 값을 넣어주면 해당 값이 변수의 current 값이 된다.
// nextId 변수를 수정하거나 조회려면 .current 값을 수정하거나 조회한다.
const nextId = useRef(4);
const onCreate = () => {
const user = {
id: nextId.current,
username,
email,
};
// 불변성을 지키면서 배열에 새 항목 추가 : spread 연산자 사용
setUsers([...users, user]);
//또는 아래와 같이 concat 함수 사용해 새로운 원소가 추가된 새로운 배열 생성
// setUsers(users.concat(user));
setInputs({
username: "",
email: "",
});
nextId.current += 1;
};
return (
<div>
<CreateUser
username={username}
email={email}
onChange={onChange}
onCreate={onCreate}
/>
<UserList users={users} />
</div>
);
}
export default App;
CreateUser.js
import React from "react";
function CreateUser({ username, email, onChange, onCreate }) {
return (
<div>
<input
name='username'
placeholder='계정명'
onChange={onChange}
value={username}
></input>
<input
name='email'
placeholder='이메일'
onChange={onChange}
value={email}
></input>
<button onClick={onCreate}>등록</button>
</div>
);
}
export default CreateUser;
UserList.js
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;
실행결과 )
배열 항목 삭제하기
App.js
해당 코드 추가 작성
UserList.js
해당 코드 추가 작성
실행결과 )
배열 항목 수정하기
User 컴포넌트에 계정명 클릭했을 때 색상 초록색으로 바뀌고 다시 누르면 검정색으로 바뀌도록 구현
App.js
import React, { useRef, useState } from "react";
import UserList from "./UserList";
import CreateUser from "./CreateUser";
function App() {
const [inputs, setInputs] = useState({
username: "",
email: "",
});
const { username, email } = inputs;
const onChange = (e) => {
const { name, value } = e.target;
setInputs({
...inputs,
[name]: value, // name 키를 가진 값을 value로 변경
});
};
const [users, setUsers] = useState([
{
id: 1,
username: "daramG",
email: "daramG@daram.com",
active: true,
},
{
id: 2,
username: "pinkbean",
email: "pinkbean@daram.com",
active: false,
},
{
id: 3,
username: "raichu",
email: "raichu@daram.com",
active: false,
},
]);
const nextId = useRef(4);
const onCreate = () => {
const user = {
id: nextId.current,
username,
email,
};
setUsers([...users, user]);
setInputs({
username: "",
email: "",
});
nextId.current += 1;
};
// UserList.js에서 onRemove(user.id)
const onRemove = (id) => {
// user.id가 파라미터로 일치하지 않는 원소 추출해서 새로운 배열 생성
// user.id가 id인 것을 제거
setUsers(
users.filter((user) => {
return user.id !== id;
})
);
};
const onToggle = (id) => {
// id 값 비교해 id가 다르면 그대로, 같아면 active값 토글
setUsers(
users.map((user) =>
user.id === id ? { ...user, active: !user.active } : user
)
);
};
return (
<div>
<CreateUser
username={username}
email={email}
onChange={onChange}
onCreate={onCreate}
/>
<UserList users={users} onRemove={onRemove} onToggle={onToggle} />
</div>
);
}
export default App;
UserList.js
import React from "react";
function User({ user, onRemove, onToggle }) {
// cursor : "pointer"
// cursor 필드 사용해 마우스 올렸을 때 커서가 손가락 모양으로 변하게 설정
return (
<div>
<b
style={{
cursor: "pointer",
color: user.active ? "green" : "black",
}}
onClick={() => onToggle(user.id)}
>
{user.username}
</b>{" "}
<span>({user.email})</span>
<button onClick={() => onRemove(user.id)}>삭제</button>
</div>
);
}
function UserList({ users, onRemove, onToggle }) {
return (
<div>
{users.map((user) => (
<User
user={user}
key={user.id}
onRemove={onRemove}
onToggle={onToggle}
/>
))}
</div>
);
}
export default UserList;
실행화면 )
'React > React 정리' 카테고리의 다른 글
React 문법 정리 2 - useState, input 상태관리, 불변성 (0) | 2023.04.06 |
---|---|
React 문법 정리 1 - 값 전달, 조건부 렌더링 (0) | 2023.03.30 |