๐ง ์ฌ์ฉํ๋ ๋๊ตฌ
๋๊ตฌ ์ค๋ช
| React | ์ฌ์ฉ์ ํ๋ฉด(UI)์ ๋ง๋ค๊ธฐ ์ํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ |
| TypeScript | ์๋ฐ์คํฌ๋ฆฝํธ์ ํ์ (์๋ฃํ)์ ์ถ๊ฐํ ์ธ์ด |
| useState | React์์ ์ํ(state)๋ฅผ ์ ์ฅํ๋ ๊ธฐ์ต์ฅ์น |
๐ง ๊ฐ๋ ๋จผ์ ์ด์ง๋ง ์ดํดํ๊ณ ๊ฐ์!
โ State (์ํ)?
- ์ฝ๊ฒ ๋งํด ๊ธฐ์ต ์ ์ฅ์
- ์ฐ๋ฆฌ๊ฐ ์ ๋ ฅํ ๋ด์ฉ, ์ถ๊ฐ๋ ํ ์ผ ๋ชฉ๋ก ๋ฑ์ ๊ธฐ์ตํด์ค
- ์ํ๊ฐ ๋ฐ๋๋ฉด ํ๋ฉด๋ ์๋์ผ๋ก ๋ค์ ๋ณด์ฌ์ค (์ด๊ฒ React์ ํต์ฌ!)
๐งฑ ์ ์ฒด ์ฝ๋ ๊ตฌ์กฐ ํ๋์ ๋ณด๊ธฐ
const [input, setInput] = useState("");
์ด๋ฆ ๋ป
| input | ์ฌ์ฉ์๊ฐ ์ ๋ ฅํ ๊ธ์ |
| setInput | ๊ทธ ๊ธ์๋ฅผ ๊ธฐ์ต์ฅ์น์ ์ ์ฅํ๋ ํจ์ |
const [todos, setTodos] = useState<Todo[]>([]);
์ด๋ฆ ๋ป
| todos | ํ ์ผ ๋ชฉ๋ก ์ ์ฒด๋ฅผ ๋ด๊ณ ์๋ ๋ฐฐ์ด |
| setTodos | ๋ชฉ๋ก์ ์ถ๊ฐํ๊ฑฐ๋ ์์ ํ๋ ํจ์ |
1๏ธโฃ ์ฌ์ฉ์ ์ ๋ ฅ ์ฒ๋ฆฌ
<input
value={input}
onChange={(e) => setInput(e.target.value)}
onKeyDown={(e) => {
if (e.key === "Enter") addTodo();
}}
/>
<button onClick={addTodo}>์ถ๊ฐ</button>
๐ก ์์ ์์ฝ
- value={input}: React์์ input์ ๊ฐ์ ๊ธฐ์ตํจ
- onChange: ์ฌ์ฉ์๊ฐ ์ ๋ ฅํ ๋๋ง๋ค input์ ์ ์ฅ
- onKeyDown: Enter ํค ๋๋ฅด๋ฉด ์ถ๊ฐ ๊ธฐ๋ฅ ์คํ
- onClick: ๋ฒํผ ๋๋ฅด๋ฉด ํ ์ผ ์ถ๊ฐ
2๏ธโฃ ํ ์ผ ์ถ๊ฐ ๊ธฐ๋ฅ
const addTodo = () => {
if (!input.trim()) return;
const newTodo = {
id: Date.now(), // ์๊ฐ์ผ๋ก ๊ณ ์ ๋ฒํธ ์์ฑ
text: input, // ์ฌ์ฉ์๊ฐ ์ด ๊ธ
isEditing: false // ์ง๊ธ ์์ ์ค์ธ์ง ์ฌ๋ถ
};
setTodos([...todos, newTodo]); // ๊ธฐ์กด ๋ชฉ๋ก(todos) ๋ค์ ๋ถ์ฌ์ ์ ์ฅํด์.
setInput(""); // ์
๋ ฅ์ฐฝ์ ๋น์์ค์.
};
๐ง ๊ฐ๋ ์์ฝ
- Date.now() → ๊ณ ์ ํ ๋ฒํธ ๋ง๋ค์ด์ฃผ๋ ํธ๋ฆญ
- ...todos, newTodo → ๊ธฐ์กด ๋ชฉ๋ก ๋ค์ ์ ํ ์ผ ์ถ๊ฐ
3๏ธโฃ ํ ์ผ ๋ชฉ๋ก ๋ณด์ฌ์ฃผ๊ธฐ
<ul>
{todos.map((todo) => (
<li key={todo.id}>
...
</li>
))}
</ul>
map() ํจ์๋ก todos ๋ฐฐ์ด์ ํ๋ํ๋ ๊บผ๋ด์ <li>๋ก ๋ณด์ฌ์ค
4๏ธโฃ ์์ ๋ชจ๋ vs ๋ณด๊ธฐ ๋ชจ๋
{todo.isEditing ? (
<input
defaultValue={todo.text}
onBlur={(e) => saveEdit(todo.id, e.target.value)}
onKeyDown={(e) => {
if (e.key === "Enter") {
saveEdit(todo.id, (e.target as HTMLInputElement).value);
}
}}
/>
) : (
<>
<span>{todo.text}</span>
<button onClick={() => startEdit(todo.id)}>์์ </button>
<button onClick={() => deleteTodo(todo.id)}>์ญ์ </button>
</>
)}
์์ ์ค๋ช
| isEditing === true | ์ ๋ ฅ์ฐฝ ๋ณด์ฌ์ค (์์ ์ค) |
| isEditing === false | ๊ธ์ + ์์ /์ญ์ ๋ฒํผ ๋ณด์ฌ์ค |
5๏ธโฃ ์์ ๊ธฐ๋ฅ ์ค๋ช
const startEdit = (id: number) => {
setTodos(todos.map((todo) =>
todo.id === id ? { ...todo, isEditing: true } : todo
));
};
- ์์ ๋ฒํผ ๋๋ฅด๋ฉด isEditing: true๋ก ๋ฐ๋
- ๊ทธ๋ฌ๋ฉด input์ฐฝ์ด ๋ํ๋จ!
6๏ธโฃ ์์ ์ ์ฅ ๊ธฐ๋ฅ
const saveEdit = (id: number, newText: string) => {
setTodos(todos.map((todo) =>
todo.id === id ? { ...todo, text: newText, isEditing: false } : todo
));
};
๊ธ์๋ฅผ ๋ฐ๊พธ๊ณ Enter ๋๋ฅด๊ฑฐ๋ ํฌ์ปค์ค๋ฅผ ์์ผ๋ฉด ์์ ์๋ฃ๋จ
7๏ธโฃ ์ญ์ ๊ธฐ๋ฅ
const deleteTodo = (id: number) => {
setTodos(todos.filter((todo) => todo.id !== id));
};
ํด๋น id๋ฅผ ๊ฐ์ง ํ ์ผ์ ์ ์ธํ ๋๋จธ์ง๋ง ๋ค์ ์ ์ฅ!
'React' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
| [React] tailwind css ์ค์น (0) | 2025.06.02 |
|---|---|
| [React] Props ๋ถ๋ชจ -> ์์ (2) | 2025.05.13 |
| [React] ์ ์ญ ์ํ zustand (0) | 2025.05.10 |
| [React] ํ์ด์ง ์ด๋ ๊ธฐ๋ฅ ๋ฃ๊ธฐ (0) | 2025.05.10 |
| [React] ๊ณตํต ํค๋(Header)์ ํธํฐ(Footer) ๋ง๋ค๊ธฐ (0) | 2025.05.10 |
