[React 기초] Todo list 만들기 :: 2) App, Container, Titlebar

도깨비젤리

·

2021. 6. 12. 16:49

개발 환경 설정


npm create-react-app TODO

 

npm install sass --save

 

npm install uuid

 

create-react-app 을 사용해서 React를 준비해준다. 추가로 나는 css 대신에 scss를 사용할 것이기 때문에, sass도 준비해두자. Vue와 달리 React에서 sass를 사용할 때 sass-loader 같은 패키지를 준비하지 않아도 된다는 점이 좋았다. 

 

추가로 uuid 라이브러리를 가져오자.  uuid는 Universal Unique Identifier (범용 단일 식별자)의 약어로, 호출한다면 랜덤으로 생성된 문자열을 반환해준다. 컴포넌트에 key값이 필요할 때 고유한 값으로 설정하기에 딱 좋다.

 

uuid를 안 쓴다면, id가 필요할 때 max_int 값을 0으로 설정한 다음, Todo Item이 추가될때마다 max_int를 증가시키고, 그 증가된 값을 id로 지정할 수도 있다. 그런데 max_int 값은 항상 페이지가 refresh 되거나, 연결이 끊어진다면 다시 호출되어 0으로 초기화 된다. 그런데 localStorage에는 이미 id가 0인 item이 있다면....?

 

Todo Items와 함께 max_int도 localStorage에 저장하면 이런 문제를 해결 할 수는 있지만, 이건 별로 스마트하지도 않고, 부서지기도 쉬운 미봉책이다. 그렇기 때문에 uuid라는 잘 만들어진 바퀴를 가져다 씁시다.

App.js


import './sass/TODO.scss'
import Container from './components/Container.js'


function App() {
  return (
    <>
      <Container></Container>
    </>
  );
}

export default App;

create-react-app으로 프로젝트를 시작하면 최상위 컴포넌트로 설정되는 곳이다. 여기서 바로 템플릿을 구성해도 되지만, 개인적으로 App이 너무 길어지면 좋지 않다고 생각한다. 코드가 길어져서 보기도 싫고, 추후 확장성을 고려하면 최상위 계층은 어떤 컴포넌트가 어디에 있는지 정도만 알려줘야한다고 생각한다.

 

그렇기 때문에, 여기서는 scss 파일만 import 해주고, Todo list의 구현은 Container 컴포넌트에게 맡깁시다.

 

 

Container.js


container 컴포넌트

 

 

import React, {useEffect, useState} from 'react'
import Titlebar from './Titlebar.js'
import InputForm from './InputForm.js'
import TODOS from './TODOS.js'



function Container (){

  // todos의 상태 관리 
  const [todos, setTodos] = useState([])

  useEffect(()=>{
    const TODOS = localStorage.getItem('TODOS')
    if(TODOS===null){
      localStorage.setItem('TODOS','[]') 
    } else{
      const parseTODOS = JSON.parse(TODOS)
      setTodos(parseTODOS)
    }
  },[])
  

  function addTodo(newTodo,id,completed){
    setTodos([...todos, {'TODO' : newTodo, 'id':id,completed:completed}])
  }
  

  function getTodos(){
    return todos
  }

  function delTodos(id){
    const result = todos.filter(({id: todoId})=>id !==todoId)
    const stringTodo = JSON.stringify(result)
    localStorage.setItem('TODOS',stringTodo)
    setTodos(result)
  }

  return(
    <div className="container">
      <Titlebar/>
      <InputForm
        addTodo={addTodo}
      />
      <hr></hr>
      <TODOS
        getTodos={getTodos}
        delTodos={delTodos}
      ></TODOS>
    </div>

  )
}
export default Container

 

Container의 역할


  1. Todo list의 탬플릿
  2. Todo list의 상태 관리

 

Container 컴포넌트가 Todo list의 CRD 기능을 하는 함수들을 다 짊어지고 있다. 하위 컴포넌트인 InputForm, TODOS 모두 Todo list의 상태와 밀접한 관련이 있으므로, 컴포넌트 각각이 상태를 가지고 있는 것보다는, 상위 컴포넌트인 Container가 두 컴포넌트에게 props로 전달하는 데이터 구조를 가지고 있어야함이 더 적절하다.

 

 

사용자에게 받은 입력을 바탕으로 Item을 생성 (Create) 하는 기능을 가진 InputForm 컴포넌트에 Create 기능을 가진 addTodo 함수를 props로 전달하고, 저장되어있는 Item을 읽고 (Read) 삭제 (Delete)하는 기능을 가진 TODOS 컴포넌트에 Read 기능을 가진 getTodosDelete 기능을 가진 delTodos를 props로 전달하자.

 

 

 

 

Titlebar.js


Titlebar 컴포넌트

 

 

import React from 'react'

function Titlebar (){
  return(
      <nav>
        <h1>오늘 할 일</h1>
      </nav>
  )
}

export default Titlebar

 

 

Titlebar.js의 역할


  1.  제목 표시

 

nav 태그를 이용해서 제목을 띄워준다.

nav 태그에 padding를 주어 h1 태그가 화면 밖으로 삐쳐나가지 않게 방지 한 것 외에는 별거 없다.