FE/React

[리액트 실습] 간단 Todo-List 만들기(추가, 삭제)

개발새발주발 2023. 2. 5. 23:43
728x90

1. 구현 화면 

첫화면 

추가기능 

삭제기능 

 

 

2. 요구사항과 컴포넌트 구조작성 

 

 

스터디를 진행하며 가장 많이 배운 것은 개발하는 마음가짐과 단계였다. 

 

개발을 진행하기 앞선 단계를 거의 안하고 바로 코딩을 시작하면서 어떻게 할 것인지 머리속으로만 구상했던 과거를 반성하며 .. 

 

이번에는 요구사항을 분석하고 컴포넌트 구조를 먼저 잡아보았다. 아직 내가 짤 수 있는 기능들에 대해서 자세히 몰라 1, 2 단계로 구성해보았다. 

 

1단계에서는 가장 근본적으로 요구하는 사항 -> TodoList에 내가 할 일을 추가하는 것과 일을 끝내면 삭제할 수 있는 기능을 넣는 것에 집중해보았다. 

 

그렇게 1단계까지 선배림과 여러가지 레퍼런스의 도움을 받아 완성해보았다. (구글과 선배림은 신이야 .. )  

 

아무튼 결론은 어떤 개발을 하더라도 뼈대를 잡는 이 과정이 매우 중요할 것이니 연습 많이 해보아야겠다 

 

 

componenets에는 2가지를 구성했다

추가를 할 수 있는 TodoCard와 리스트 형태로 나타내는 TodoList 이다. 

 

3. TodoCard.jsx

import React, { useRef, useState } from 'react'

export default function TodoCard({ todoList, setTodoList }) {
    const newId = useRef(4);
    const [newTodo,setNewTodo] = useState("")
    const [newMemo,setNewMemo] = useState("")
    //const [newDone,setNewDone] = useState(false)

  
    const addTodo = () => {
        const newTodoList = [...todoList];
        // newTodoList 배열에 새롭게 받은 todoList를 추가해준다. 
        const newTodoObj = {
            id: newId.current,
            //current를 통해 생성될 때마다 다른 Id를 부여할 수 있도록 해준다. 
            title : newTodo,
            content: newMemo,
            done : newDone,
          }
          //Id값 이전값에 대해 +1씩 하기
          newId.current++;
        newTodoList.push(newTodoObj);
        setTodoList(newTodoList);
    }

  return (
    <div className ="card-container">
        <div className='titleWrap'>
            오늘의 할일을 입력해주세요

        </div>
        <br/>
        <div className="todoWrap">
            <div className = "inputTodoWrap">
                <input className='input'
                    placeholder='To-do '
                    value={newTodo}
                    onChange={(e) => setNewTodo(e.target.value)}
                /> 

            </div>

            <div style = {{marginTop:"20px"}} className = "inputMemoWrap">
                <input className='input'
                placeholder='메모'
                value = {newMemo}
                onChange={(e)=> setNewMemo(e.target.value)}
                /> 
            </div>

            <div>
                <button onClick={addTodo} className = "cardButton">
                    업로드
                </button>
            </div>
        </div>
    </div>
  )
}

각 todoitem(반복되는 요소)에 고유한 Id 값을 부여하기 위해 useRef를 사용하였다. 

 

Hooks API Reference – React

A JavaScript library for building user interfaces

ko.reactjs.org

 

 

4. TodoList.jsx

import React, { useState } from 'react'


const TodoList= ({ todoList,setTodoList }) => {
    

    const deleteTodo=(id)=>{
        // todoList(setTodoList.filter(a => a.id !== it.id));
        const newTodoList=todoList.filter(a=>a.id !== id);
        
        setTodoList(newTodoList)
    }


    return (
        <div className='list-container'>
        <div className="TodoList">
            <h3>Todo List</h3>
            <h4>{todoList.length}개의 할 일이 있습니다.</h4>
            <div>
                {todoList.map((it)=>(
                    <div className="item-wrap" key={it.id}>
                        <div>
                            <input type="checkbox" id="check1" />
                            <label for ="check1"></label>
                        </div>

                        <div>
                        <div className='title-container'>{it.title} </div>
                        <div className='memo-container'>{it.content}</div>
                        </div>
                        
                        
                        <div>
                        <button 
                        className = "deleteBtn"
                        onClick={()=> {deleteTodo(it.id)}}>
                            삭제</button>

                        </div>
                    </div>
                ))}
            </div>
            {/* 여기가 끝 !!  */}
        </div>
        </div>
    );
}

// TodoList.defaultProps={
//     TodoList:[],
// };

export default TodoList;

추가는 map함수, 삭제는 filter함수를 사용하였다. 

map 함수는 for문을 이용하지 않고 배열의 원소들 모두 각각 특정한 함수를 적용시킬 수 있다. 

 

Array.prototype.map() - JavaScript | MDN

map() 메서드는 배열 내의 모든 요소 각각에 대하여 주어진 함수를 호출한 결과를 모아 새로운 배열을 반환합니다.

developer.mozilla.org

filter함수는 이름과 역할이 같다! 주어진 함수를 만족시키는 원소들만으로 구성된 새로운 배열을 반환한다. 

 

Array.prototype.filter() - JavaScript | MDN

filter() 메서드는 주어진 함수의 테스트를 통과하는 모든 요소를 모아 새로운 배열로 반환합니다.

developer.mozilla.org

 

5. App.js

import { useRef, useState } from "react";
import TodoCard from "./componenets/TodoCard";
import TodoList from "./componenets/TodoList";
import newList from "./componenets/TodoList";



//dummy data 넣어보기 
const dummy = [
  {
    id: 1,
    title : "첫번째 해야할 일 ",
    content: "12시, 집 ",
    done : true,
  },
  {
    id: 2,
    title : "두번째 해야할 일 ",
    content: "13시, 학교 ",
    done : true,
  },
  {
    id: 3,
    title : "세번째 해야할 일 ",
    content: "14시, 도서관 ",
    done : false,
  }
]




function App() {
  const [todoList, setTodoList] = useState(dummy);
  
  return (
    <div className="App">

      <TodoList todoList={todoList} setTodoList={setTodoList}/>
      <TodoCard todoList={todoList} setTodoList={setTodoList}/>
      
    </div>
  );
}

export default App;
 

5. props 를 통해 컴포넌트에게 값 전달하기 · GitBook

5. props 를 통해 컴포넌트에게 값 전달하기 이번에는 컴포넌트의 props 라는 개념에 대해서 알아보겠습니다. props 는 properties 의 줄임말입니다. 우리가 어떠한 값을 컴포넌트에게 전달해줘야 할 때,

react.vlpt.us

컴포넌트 전달을 잘 하자... !