2025 / 03 / 25
오늘 수업 시간에는 투두리스트의 기능과 비슷한 메모장을 만들어보았습니다. 확실히 투두리스트와 구조가 비슷해서 구현하는 것에 어려움은 없었습니다. props 전달에서 헷갈리는 부분이 있어서 그 부분을 중심으로 정리해보겠습니다.
리액트에서 상태 관리와 컴포넌트 구조
import { useState } from "react"; import "./App.css"; import Mainbox1 from "./components/Mainbox1"; import Mainbox2 from "./components/Mainbox2"; function App() { const [list, setList] = useState([]); return ( <div className="container_box"> <Mainbox1 setList={setList} /> <hr /> <Mainbox2 lists={list} /> </div> ); } export default App;
useState([])를 사용하여 list라는 상태를 관리합니다.- 초기값은 빈 배열 []입니다.
- 이 상태는 메모 목록을 저장합니다.
- setList : list 상태를 업데이트하는 함수입니다.
<div className="container_box">
<Mainbox1 setList={setList} />
<hr />
<Mainbox2 lists={list} />
메모 추가 입력
import { useState } from "react"; export default function Mainbox1({ setList }) { const [title, setTitle] = useState(""); const [text, setText] = useState(""); function TitleChange(e) { setTitle(e.target.value); } function TextChange(e) { setText(e.target.value); } function add(e) { if (e && e.key === "Enter") { console.log("엔터 입력"); } let today = new Date(); let year = today.getFullYear(); let month = ("0" + (today.getMonth() + 1)).slice(-2); let day = ("0" + today.getDate()).slice(-2); let dateString = year + "년 " + month + "월 " + day + "일 "; let hours = ("0" + today.getHours()).slice(-2); let minutes = ("0" + today.getMinutes()).slice(-2); let seconds = ("0" + today.getSeconds()).slice(-2); let timeString = hours + "시 " + minutes + "분 " + seconds + "초 "; setList((todos) => [ ...todos, { id: Math.random() + "", text: title, info: text, date: dateString, time: timeString, }, ]); setTitle(""); setText(""); } function OnKeyUp(e) { if (e.key === "Enter") { add(e); } } return ( <div className="main_box1"> <h1>🤍 메모장 🤍</h1> <div className="inputs"> <input type="text" className="input_title" placeholder="제목 입력" onChange={TitleChange} onKeyUp={OnKeyUp} value={title} /> <input type="text" className="input_info" placeholder="내용 입력" onChange={TextChange} onKeyUp={OnKeyUp} value={text} /> </div> <button className="add_memo" onClick={add}> 메모 추가하기 </button> </div> ); }
title, text
- 각각 제목과 내용의 상태를 관리합니다.
- 초기값은 빈 문자열입니다.
TitleChange, TextChange
- 제목 입력 필드와 내용 입력 필드에서 사용자가 입력할 때마다 상태를 업데이트하는 함수입니다.
add 함수
- 메모를 추가하는 함수입니다.
- 메모를 추가할 때 현재 시간을 포맷화하여 date와 time을 생성합니다.
- new Date( )를 사용하여 현재 날짜와 시간을 가져옵니다.
- setList를 호출하여 새로운 메모를 list 상태에 추가합니다.
- 이전 상태(todos)에 새로운 메모를 추가하는 방식으로 처리됩니다.
Math.random() + "": 메모마다 고유한 id를 생성하는 방법입니다.
<div className="main_box1">
<div>입니다.<h1>🤍 메모장 🤍</h1>
<div className="inputs">
<input> 요소를 묶은 컨테이너입니다.input for title
input for content
onKeyUp={OnKeyUp}
<button className="add_memo" onClick={add}>
메모 목록 표시
function List({ list }) { return ( <div className="memo_box"> <div className="time"> <p>{list.date}</p> <p>{list.time}</p> </div> <hr className="sub_hr" /> <ul> <li className="li_title">{list.text}</li> <li>{list.info}</li> </ul> </div> ); } export default function Mainbox2({ lists }) { return ( <div className="main_box2"> {lists.length === 0 ? ( <p>메모가 없어요! ૮꒰´ᵔ⑅꒱ა</p> ) : ( <ul className="mobile-list"> {lists.map((list) => { return <List key={list.id} list={list} />; })} </ul> )} </div> ); }
List 컴포넌트
- 각 메모 항목을 화면에 출력하는 역할을 합니다.
- list 객체를 props로 받아와서, 해당 메모의 제목, 내용, 날짜, 시간 등을 표시합니다.
- list.date와 list.time을
<p>요소로 감싸서 날짜와 시간을 출력합니다.<ul>과<li>를 사용하여 메모의 제목(list.text)과 내용을(list.info) 출력합니다.
Mainbox2
- lists 배열을 props로 받아와서, 이를 화면에 렌더링합니다.
- 만약 메모가 없다면 "메모가 없어요!"라는 텍스트를 표시합니다.
- lists 배열을 순회하면서 각 메모 항목을 List 컴포넌트로 전달하여 렌더링합니다.
- 각 메모는 key prop을 통해 고유하게 식별됩니다.
<div className="main_box2">
{lists.length === 0 ? <p>메모가 없어요!</p> : ...}
<ul className="mobile-list">
<ul> 요소입니다.{lists.map((list) => { return <List key={list.id} list={list} />; })}
- useState를 통해 상태 관리
- props를 이용한 부모-자식 컴포넌트 간 데이터 전달
- 조건부 렌더링과 배열 순회 (map( ))를 사용한 동적 화면 업데이트
- 이벤트 처리 : onChange, onKeyUp, onClick 등 이벤트 핸들링
54일차 후기
- 배운 내용을 복습할 겸 To-Do List만 만들다가 이번에 처음으로 메모장을 만들게 되었는데, 생각보다 어렵거나 헷갈리는 부분이 없어서 다행이었습니다.
- 조건부 렌더링을 하는 과정에서 계속 까먹고 if를 사용하려고 해서 오류를 띄웠습니다.
- 그래도 마지막에는 삼항 연산자를 사용하여 잘 해결했습니다.
- 전체적인 구조가 To-Do List랑 다르지 않아서 어렵지는 않았습니다.
- 배열 순회도 하는 방법에 사용되는 key 값이 뭔가.. 어려워서 고민이었는데, 계속 사용하다 보니까 이제는 그냥 원하는 곳에 사용할 수 있게 되었습니다.
- 혼자 만들어본 실습 예제인데 배운 내용을 복습할 수 있어서 좋았습니다. ๑╹ワ╹๑