본문 바로가기
Frontend/Frontend 프로젝트

React App 만들기 - 메모 기능 구현하기 2

by 천우산__ 2023. 6. 21.

구현이 필요한 기능들

구현한 적 있는 기능

  1. 현재 시간 알려주는 기능 (시계)
  2. 날씨 정보를 반환하는 기능 (API)
  3. 할 일을 등록할 수 있는 기능 (Form)
  4. 할 일 리스트를 보여주는 영역 (Todo-list)
  5. 할 일을 지울 수 있는 기능

새롭게 구현해 보고 싶은 기능

  1. 만다라트 생성
  2. 날씨 현황에 따른 배경화면 이펙트

다음으로는, 할 일을 지울 수 있는 기능을 추가해야 한다.

그 전에, 이전에 만들었던 코드 내용을 보면, 텍스트만 표기되기 때문에, 할 일 리스트에 중복된 데이터가 들어가는 경우

어떤 데이터를 지울지 식별하기 어려움이 있으므로, 할 일 데이터를 배열이 아닌 object 형식으로 변경하고, 각 할 일 에는

할 일의 Id값과 할 일의 value (내용) 을 추가하는 코드로 변경해야 한다.

import { useState } from 'react';

function Todos() {
    const [todoList, setTodoList] = useState([]);
    
    const submitFunction = (event) => {
        event.preventDefault();
        const todoId = todoList.length + 1;
        const todoValue = event.target.todo.value;
        
        // 변경된 부분
        const todo = {
            todoId,
            todoValue
        }

        setTodoList([...todoList, todo ]);
        event.target.todo.value = '';
    }

    return (
        <div>
            <div className='todoListArea'> todo-list will here </div>
            
            <div>
             // 여기에 할 일 들이 들어가야 합니다.
            </div>

            <form onSubmit={submitFunction}> 
                <input type='text' name='todo' placeholder='write your todoList'/>
            </form>
        </div>
    )
}
export default Todos;

그 다음 단계로는, 각 할 일 들을 받아서, 리스트 형식으로 만들어 주는 작업이 필요한데,

리스트 태그를 사용하는 것도 가능하지만, div 태그를 통해 구분하는 것으로 구현하였다.

import { useState } from 'react';

function Todos() {
    const [todoList, setTodoList] = useState([]);
    
    const submitFunction = (event) => {
        event.preventDefault();
        const todoId = todoList.length + 1;
        const todoValue = event.target.todo.value;
        
        const todo = {
            todoId,
            todoValue
        }

        setTodoList([...todoList, todo ]);
        event.target.todo.value = '';
    }

    return (
        <div>
            <div className='todoListArea'> todo-list will here </div>
            
            
            <div>
            	// 추가한 부분
                {todoList.map((item) => {
                    return (
                    	<div key={item.todoId}> {item.todoValue} <buttom> x </button></div>
                    )
                })}
            </div>

            <form onSubmit={submitFunction}> 
                <input type='text' name='todo' placeholder='write your todoList'/>
            </form>
        </div>
    )
}
export default Todos;

기존에 있는 todoList 를 순환 하면서, 새로운 div 태그 내 todoList 값을 반환하도록 map 함수를 사용하였다.

div 태그 안 key 값은, 반복 함수를 통해 새로운 태그를 생성하는 경우, 각 데이터를 식별할 고유 값을 정해주어야 하기 때문에

todoList의 todoId를 넣어 주었다. (해당 설정은 필수는 아니지만, 기능이 실행되는 경우 경고가 날아온다.)

추가적으로 버튼 x 를 누르면 삭제할 수 있도록 임시로 태그를 넣어주었다.

다음으로는 x 버튼을 눌렀을 때 원하는 기능을 수행할 수 있도록 함수를 작성 해 준다.

import { useState } from 'react';

function Todos() {
    const [todoList, setTodoList] = useState([]);
    
    const submitFunction = (event) => {
        event.preventDefault();
        const todoId = todoList.length + 1;
        const todoValue = event.target.todo.value;
        
        const todo = {
            todoId,
            todoValue
        }

        setTodoList([...todoList, todo ]);
        event.target.todo.value = '';
    }
    
    // 할 일 삭제 기능 추가
    const deleteTodo = (deleteItem) => {
        console.log(deleteItem);
        const newTodo = todoList.filter((i) => {return i.todoId !== deleteItem })

        setTodoList(newTodo);
    }

    return (
        <div>
            <div className='todoListArea'> todo-list will here </div>
            
            <div>
                {todoList.map((item) => {
                    return (
                    
                    	// 함수 추가
                    	<div key={item.todoID}> {item.todoValue} <button onClick={() => deleteTodo(item.todoId)}> x </button> </div>
                    )
                })}
            </div>

            <form onSubmit={submitFunction}> 
                <input type='text' name='todo' placeholder='write your todoList'/>
            </form>
        </div>
    )
}
export default Todos;

 

이 기능들은 따로 빼줘도 될 것 같다. 그래서 EachTodo 라는 새로운 fucntion 을 생성하고 그 안에 할 일 표기와 삭제의 기능들을 넣어주자

import { useState } from 'react';

function EachTodo({ item, deleteTodo }) {
    return (    
        <div>
            {item.todoValue} <button onClick={() => deleteTodo(item.todoId)}> x </button>
        </div>
    );
}

function Todos() {
    const [todoList, setTodoList] = useState([]);
    
    const submitFunction = (event) => {
        event.preventDefault();
        const todoId = todoList.length + 1;
        const todoValue = event.target.todo.value;
        
        const todo = {
            todoId,
            todoValue
        }

        setTodoList([...todoList, todo ]);
        event.target.todo.value = '';
    }

    const deleteTodo = (deleteItem) => {
        const newTodo = todoList.filter((i) => { return i.todoId !== deleteItem })
        setTodoList(newTodo);
    }
    
    return (
        <div>
            <div className='todoListArea'> todo-list will here </div>
            
            <div>
                {todoList.map((item) => {
                    return <EachTodo key={ item.todoId } item={ item } deleteTodo={deleteTodo}  />
                })}
            </div>

            <form onSubmit={submitFunction}> 
                <input type='text' name='todo' placeholder='write your todoList'/>
            </form>
        </div>
    )
}
export default Todos;

할 일을 삭제하는 기능 (deleteTodo) 를 메인 앱 (Todos) 안에 넣어둔 이유는,

해당 기능까지 별도 앱으로 옮기는 경우, todoList 와 setTodoList 를 인식하지 못하게 된다. 해결 방법은

  1. delete 함수를 별도의 앱으로 옮겨주고, todoList 와 setTodoList를 해당 앱으로 같이 넘겨준다.
  2. delete 함수만 넘겨준다.

2가지 선택지가 있지만, 1번의 경우가 넘겨주는 데이터가 적어, 관리하기 편하기 때문에 위와 같이 작성했다.