54일차[React (복습) 메모장 만들기]

진하의 메모장·2025년 3월 28일
1

공부일기

목록 보기
58/66
post-thumbnail

2025 / 03 / 25

오늘 수업 시간에는 투두리스트의 기능과 비슷한 메모장을 만들어보았습니다. 확실히 투두리스트와 구조가 비슷해서 구현하는 것에 어려움은 없었습니다. props 전달에서 헷갈리는 부분이 있어서 그 부분을 중심으로 정리해보겠습니다.



💌 App 컴포넌트

리액트에서 상태 관리와 컴포넌트 구조

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;


1. 작동 원리

  • useState([])를 사용하여 list라는 상태를 관리합니다.
  • 초기값은 빈 배열 []입니다.
  • 이 상태는 메모 목록을 저장합니다.
  • setList : list 상태를 업데이트하는 함수입니다.


2. 코드 설명

<div className="container_box">

  • App 컴포넌트의 외부 컨테이너 역할을 하며, CSS 클래스를 통해 스타일링이 가능합니다.

<Mainbox1 setList={setList} />

  • Mainbox1 컴포넌트를 렌더링합니다.
  • 여기서 setList 함수는 Mainbox1 컴포넌트에 props로 전달되어, 사용자가 메모를 추가할 때 이 함수를 사용해 App의 list 상태를 업데이트합니다.

<hr />

  • 구분선을 추가하여 Mainbox1과 Mainbox2 컴포넌트를 시각적으로 구분합니다.

<Mainbox2 lists={list} />

  • list 상태를 Mainbox2에 전달하여, 메모 목록을 화면에 표시할 수 있도록 합니다.


💌 Mainbox1 컴포넌트

메모 추가 입력

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>
   );
}


1. 작동 원리

title, text

  • 각각 제목과 내용의 상태를 관리합니다.
  • 초기값은 빈 문자열입니다.

TitleChange, TextChange

  • 제목 입력 필드와 내용 입력 필드에서 사용자가 입력할 때마다 상태를 업데이트하는 함수입니다.

add 함수

  • 메모를 추가하는 함수입니다.
  • 메모를 추가할 때 현재 시간을 포맷화하여 date와 time을 생성합니다.
  • new Date( )를 사용하여 현재 날짜와 시간을 가져옵니다.
  • setList를 호출하여 새로운 메모를 list 상태에 추가합니다.
  • 이전 상태(todos)에 새로운 메모를 추가하는 방식으로 처리됩니다.
  • Math.random() + "" : 메모마다 고유한 id를 생성하는 방법입니다.


2. 코드 설명

<div className="main_box1">

  • Mainbox1의 컨테이너 <div>입니다.
  • 이 안에 제목, 내용 입력 필드, 메모 추가 버튼이 들어 있습니다.

<h1>🤍 메모장 🤍</h1>

  • 메모장 제목을 화면에 표시합니다.

<div className="inputs">

  • 제목과 내용을 입력할 수 있는 두 개의 <input> 요소를 묶은 컨테이너입니다.

input for title

  • 제목을 입력하는 텍스트 박스입니다.
  • onChange 이벤트에서 setTitle을 호출하여 입력값을 상태에 반영합니다.

input for content

  • 내용을 입력하는 텍스트 박스입니다.
  • onChange 이벤트에서 setText를 호출하여 입력값을 상태에 반영합니다.

onKeyUp={OnKeyUp}

  • 사용자가 Enter 키를 누르면 add 함수가 호출됩니다.

<button className="add_memo" onClick={add}>

  • 메모를 추가하는 버튼입니다.
  • 버튼을 클릭하면 add 함수가 호출됩니다.


💌 Mainbox2 컴포넌트

메모 목록 표시

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>
   );
}


1. 작동 원리

List 컴포넌트

  • 각 메모 항목을 화면에 출력하는 역할을 합니다.
  • list 객체를 props로 받아와서, 해당 메모의 제목, 내용, 날짜, 시간 등을 표시합니다.
  • list.date와 list.time을 <p> 요소로 감싸서 날짜와 시간을 출력합니다.
  • <ul><li>를 사용하여 메모의 제목(list.text)과 내용을(list.info) 출력합니다.

Mainbox2

  • lists 배열을 props로 받아와서, 이를 화면에 렌더링합니다.
  • 만약 메모가 없다면 "메모가 없어요!"라는 텍스트를 표시합니다.
  • lists 배열을 순회하면서 각 메모 항목을 List 컴포넌트로 전달하여 렌더링합니다.
  • 각 메모는 key prop을 통해 고유하게 식별됩니다.


2. 코드 설명

<div className="main_box2">

  • Mainbox2의 외부 컨테이너입니다.
  • 이 안에 메모 목록이 표시됩니다.

{lists.length === 0 ? <p>메모가 없어요!</p> : ...}

  • 조건부 렌더링을 사용하여, lists 배열이 비어 있으면 "메모가 없어요!"라는 문구를 출력하고, 메모가 하나라도 있으면 리스트 항목을 렌더링합니다.

<ul className="mobile-list">

  • 메모 목록을 출력하는 <ul> 요소입니다.

{lists.map((list) => { return <List key={list.id} list={list} />; })}

  • lists 배열을 순회하여 각 list를 List 컴포넌트로 전달하고, 이를 화면에 표시합니다.


💌 사용된 리액트 개념

  1. useState를 통해 상태 관리
  2. props를 이용한 부모-자식 컴포넌트 간 데이터 전달
  3. 조건부 렌더링과 배열 순회 (map( ))를 사용한 동적 화면 업데이트
  4. 이벤트 처리 : onChange, onKeyUp, onClick 등 이벤트 핸들링



54일차 후기

  • 배운 내용을 복습할 겸 To-Do List만 만들다가 이번에 처음으로 메모장을 만들게 되었는데, 생각보다 어렵거나 헷갈리는 부분이 없어서 다행이었습니다.
  • 조건부 렌더링을 하는 과정에서 계속 까먹고 if를 사용하려고 해서 오류를 띄웠습니다.
  • 그래도 마지막에는 삼항 연산자를 사용하여 잘 해결했습니다.
  • 전체적인 구조가 To-Do List랑 다르지 않아서 어렵지는 않았습니다.
  • 배열 순회도 하는 방법에 사용되는 key 값이 뭔가.. 어려워서 고민이었는데, 계속 사용하다 보니까 이제는 그냥 원하는 곳에 사용할 수 있게 되었습니다.
  • 혼자 만들어본 실습 예제인데 배운 내용을 복습할 수 있어서 좋았습니다. ๑╹ワ╹๑
profile
૮꒰ ྀི〃´꒳`〃꒱ა

0개의 댓글