[React] useRef์ ์ํ ๋์ด์ฌ๋ฆฌ๊ธฐ (#09-2)
- React
![[React] useRef์ ์ํ ๋์ด์ฌ๋ฆฌ๊ธฐ (#09-2)](https://coursework.vschool.io/content/images/size/w2000/2017/08/react-banner.png)
๐ ์ฐ๊ด ํฌ์คํ
Github
์๋ก
์ ๋ ฅ ํผ์์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ฌ ๋, ๋ชจ๋ ํค ์ ๋ ฅ๋ง๋ค ์ํ๋ฅผ ์ ๋ฐ์ดํธํ๋ ๋์ "์ ์ฅ" ๋ฒํผ์ ๋๋ฅด๋ ์์ ์๋ง ๊ฐ์ ์ฝ์ด์ค๊ณ ์ถ๋ค๋ฉด Ref ์ฌ์ฉํ์
-> ์๋๋ฉด ์ํ ๋ณํ๋ฅผ ๊ณ์ ํ๋ก์ ํ ํ์๊ฐ ์์ผ๋๊น..
์ฌ์ค useState๋ก๋ ๊ตฌํ ๊ฐ๋ฅํ์ง๋ง ์ useRef๋ฅผ ์ฌ์ฉํด์ผํ ๊น?
useState ์ useRef์ ์ฐจ์ด
| ๋น๊ต ํญ๋ชฉ | useState (์ ์ด ์ปดํฌ๋ํธ) | useRef (๋น์ ์ด ์ปดํฌ๋ํธ) |
|---|---|---|
| ๋ฆฌ๋ ๋๋ง | ๊ฐ์ด ๋ฐ๋ ๋๋ง๋ค ๋ฐ์ (๋งค ํค์ ๋ ฅ ์) | ๋ฐ์ํ์ง ์์ |
| ์ค์๊ฐ ๊ฒ์ฌ | ๊ฐ๋ฅ (๊ธ์ ์ ์ ํ, ์ ๋ ฅ ์ฆ์ ๊ฒฝ๊ณ ๋ฑ) | ๋ถ๊ฐ๋ฅ (๋ฒํผ์ ๋๋ฅด๋ ์์ ์๋ง ํ์ธ ๊ฐ๋ฅ) |
| UI ๋๊ธฐํ | ์ ๋ ฅ๊ฐ์ ๋ฐ๋ผ UI๊ฐ ์ฆ์ ๋ณํจ | ์ ์ฅ ์ ๊น์ง UI ๋ณํ ์์ |
| ์ถ์ฒ ์ํฉ | ๋ณต์กํ ์ ํจ์ฑ ๊ฒ์ฌ, ์ค์๊ฐ ํผ๋๋ฐฑ ํ์ ์ | ๋จ์ํ ๋ฐ์ดํฐ ์์ง, ์ฑ๋ฅ ์ต์ ํ ํ์ ์ |
1. useRef๋ฅผ ์ด์ฉํ ์ ๋ ฅ๊ฐ ์์ง
useState๋ฅผ ์ฐ๋ฉด ์ฝ๋๊ฐ ๋ณต์กํด์ง ์ ์๋ ์ํฉ์์ useRef๋ฅผ ์ฌ์ฉํ๋ฉด DOM ์์์ ์ง์ ์ ๊ทผํ์ฌ ํ์ํ ๋๋ง ๊ฐ์ ๊ฐ์ ธ์ฌ ์ ์๋ค.
import { useRef } from 'react';
const title = useRef();
const description = useRef();
const dueDate = useRef();
function handleSave() {
const enteredTitle = title.current.value;
const enteredDescription = description.current.value;
const enteredDueDate = dueDate.current.value;
// ์์ง๋ ๋ฐ์ดํฐ๋ฅผ ์์ ์ปดํฌ๋ํธ๋ก ์ ๋ฌ
onAdd({
title: enteredTitle,
description: enteredDescription,
dueDate: enteredDueDate
});
}2. ์ปค์คํ
์ปดํฌ๋ํธ์ Ref ์ ๋ฌํ๊ธฐ (forwardRef)
๋ด์ฅ HTML ํ๊ทธ(input, textarea)๊ฐ ์๋ ์ปค์คํ
์ปดํฌ๋ํธ์ ref ์์ฑ์ ๋๊ธฐ๋ ค๋ฉด React์ forwardRef๋ฅผ ์ฌ์ฉํด์ผ ํ๋ค.
import { forwardRef } from 'react';
const Input = forwardRef(function Input({ label, textarea, ...props }, ref) {
return (
<p>
<label>{label}</label>
{textarea ? (
<textarea ref={ref} {...props} />
) : (
<input ref={ref} {...props} />
)}
</p>
);
});forwardRef๋ก ๊ฐ์ผ ์ปดํฌ๋ํธ๋ ๋ ๋ฒ์งธ ์ธ์๋กref๋ฅผ ์ ๋ฌ๋ฐ์ผ๋ฉฐ, ์ด๋ฅผ ๋ด๋ถ์ ์ค์ DOM ์์์ ์ฐ๊ฒฐํ ์ ์๋ค.
3. ์ํ ๋์ด์ฌ๋ฆฌ๊ธฐ: App์์ ๋ฐ์ดํฐ ๊ด๋ฆฌ
์์ฑ๋ ํ๋ก์ ํธ ๋ฐ์ดํฐ๋ ์ฌ์ด๋๋ฐ์ ์์ธ ํ๋ฉด ๋ชจ๋์์ ํ์ํ๋ฏ๋ก, ๊ฐ์ฅ ๊ณตํต ๋ถ๋ชจ์ธ App ์ปดํฌ๋ํธ์์ ์ํ๋ฅผ ๊ด๋ฆฌํ๋ค.
// App.jsx
function handleAddProject(projectData) {
setProjectsState(prevState => {
const newProject = {
...projectData,
id: Math.random() // ๊ฐ๋จํ ID ์์ฑ
};
return {
...prevState,
projects: [...prevState.projects, newProject] // ๊ธฐ์กด ๋ฐฐ์ด ๋ณต์ฌ ํ ์ ํ๋ก์ ํธ ์ถ๊ฐ
};
});
}
// ...๋ ๋๋ง ๋ถ๋ถ
<NewProject onAdd={handleAddProject} />4. ์ ๋ ฅ ํ์ ์ต์ ํ (Date Picker)
์ฌ์ฉ์๋ก๋ถํฐ ์ ํํ ๋ ์ง ํ์์ ๋ฐ๊ธฐ ์ํด input์ type ์์ฑ์ ํ์ฉํ๋ค.
<Input type="text" ref={title} label="Title" />
<Input textarea ref={description} label="Description" />
<Input type="date" ref={dueDate} label="Due Date" />type="date"๋ฅผ ์ค์ ํ๋ฉด ๋ธ๋ผ์ฐ์ ๋ด์ฅ ๋ฐ์ดํธ ํผ์ปค(Date Picker)๊ฐ ํ์ฑํ๋์ด ํธ๋ฆฌํ๊ฒ ๋ ์ง๋ฅผ ์ ํํ ์ ์๋ค.
๐ก ์์ฝ ๋ฐ ํต์ฌ ํฌ์ธํธ
- Ref vs State: ์ค์๊ฐ ์ ํจ์ฑ ๊ฒ์ฌ๊ฐ ํ์ ์๋ค๋ฉด
useRef๊ฐ ๋ ๋๋ง ์ต์ ํ์ ์ฝ๋ ๊ฐ๊ฒฐ์ฑ ๋ฉด์์ ์ ๋ฆฌํ๋ค. - forwardRef: ์ปค์คํ
์ปดํฌ๋ํธ๋ฅผ ์ค๊ณํ ๋ ์ธ๋ถ์์ ์ ์ดํ ์ ์๋๋ก
forwardRef๋ฅผ ์ ์ฉํ๋ ์ต๊ด์ ๋ค์ด์. - ๋ถ๋ณ์ฑ ์ ์ง: ์ํ ๋ฐฐ์ด์ ์
๋ฐ์ดํธํ ๋๋
[...prevState.projects, newProject]์ ๊ฐ์ด ๊ธฐ์กด ๋ฐ์ดํฐ๋ฅผ ๋ณต์ฌํ์ฌ ๋ถ๋ณ์ฑ์ ์ง์ผ์ผ ํ๋ค.
5. ๋ฐ๋ชจ
๋ค์ ๋จ๊ณ: ๋ฐ์ดํฐ ์ ์ฅ ๋ก์ง์ ์์ฑ๋์๋ค. ๋ค์์๋ ์ ๋ ฅ๊ฐ์ด ๋น์ด์์ ๋ ๊ฒฝ๊ณ ๋ฅผ ๋์ฐ๋ **์ ํจ์ฑ ๊ฒ์ฌ(Validation)**์ ๋ชจ๋ฌ(Modal) ์ฐฝ ๊ตฌํ ๋ฐฉ๋ฒ์ ์์๋ณด์.
KEEP READING
Related writing

Woojin
๊ตฌ์กฐ์ ์ผ๋ก ์ฌ๊ณ ํ๊ณ , ๊ทผ๊ฑฐ ์๊ฒ ๊ตฌํํ๊ธฐ ์ํด ๊ธฐ๋กํฉ๋๋ค.
