useRef로 컴포넌트 안의 변수 만들기 & 배열에 항목 추가하기
useRef로 컴포넌트 안의 변수 만들기 & 배열에 항목 추가하기
컴포넌트에서 특정 DOM을 선택해야할 때 -> ref 사용
함수형 컴포넌트에서 이를 설정할 때 -> useRef 사용
useRef Hook은 DOM을 선택하는 용도 외에도, 컴포넌트 안에서 조회 및 수정할 수 있는 변수를 관리함.
App 컴포넌트에서 userRef를 사용해 변수를 관리하려 한다.
사용하려는 목적은 배열에 새 항목을 추가하려 할 때, 새 항목에서 사용 할 고유 id를 관리하는 용도이다.
useRef를 사용하여 변수를 관리하기 전에 배열을 App에서 선언하고 UserList에게 props로 전달해주는 방식으로 만들 것이다.
1. useRef로 컴포넌트 안의 변수 만들기
App.js
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);
const onCreate = () => {
// 나중에 구현 할 배열에 항목 추가하는 로직
// ...
nextId.current += 1;
};
return <UserList users={users} />;
}
export default App;
userRef() 를 사용할 때 파라미터를 넣어주면 이 값이 .current값의 기본값이 된다.
그리고 이 값을 수정할 때 .current 값을 수정하면 되고 조회할 때는 .current를 조회하면 된다.
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;
2. 배열에 항목 추가하기
배열에 새로운 항목을 추가하려 한다.
일단 input두개와 button 하나로 이루어진 CreateUser.js 컴포넌트를 src 안에 만들어준다.
CreateUser.js
import React from 'react';
function CreateUser({ username, email, onChange, onCreate }) {
return (
<div>
<input
name="username"
placeholder="계정명"
onChange={onChange}
value={username}
/>
<input
name="email"
placeholder="이메일"
onChange={onChange}
value={email}
/>
<button onClick={onCreate}>등록</button>
</div>
);
}
export default CreateUser;
상태관리를 CreateUser에서 하지 않고 부모 컴포넌트인 App에서 하게 하고, input의 값 및 이벤트로 등록할 함수들을 props로 넘겨받아서 사용해주려한다.
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
});
};
const [users, setUsers] = useState([
{
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);
const onCreate = () => {
const user = {
id: nextId.current,
username,
email
};
setUsers([...users, user]);
setInputs({
username: '',
email: ''
});
nextId.current += 1;
};
return (
<>
<CreateUser
username={username}
email={email}
onChange={onChange}
onCreate={onCreate}
/>
<UserList users={users} />
</>
);
}
export default App;
- input에 값을 입력하고 등록 버튼을 눌렀을 때 input 값들이 잘 초기화 되도록 만들어줬다.
- users도 useState를 사용해 컴포넌트 상태로서 관리해줬다.
- 불변성을 지키면서 배열에 새 항목을 추가해주기 위해 spread 연산자를 사용해줬다.
+ 추가로 concat함수를 사용해서 기존의 배열을 수정하지 않고, 새로운 원소가 추가된 새로운 배열을 만들어주는 방법도 있다.
App.js에서 concat함수를 사용한 부분
const nextId = useRef(4);
const onCreate = () => {
const user = {
id: nextId.current,
username,
email
};
setUsers(users.concat(user));
🔑 핵심 포인트
spread 연산자 사용
- setUsers([...users, user]);
Concat 함수 사용
- setUsers(users.concat(user));
✨ 부모 컴포넌트에서 state 값(input 등등)과 함수를 작성하고 자식 컴포넌트에게 전달하는 구조를 기억하자