결과 화면


1. 바닐라 자바스크립트로 투두 리스트 만들기

  • index.html
<body>
    <h1>To dos</h1>

    <form>
        <input type="text">
        <button>Confirm</button>
    </form>

    <ul></ul>
</body>

 

  • index.js
// html 태그 선택
const form = document.querySelector('form')
const input = document.querySelector('input')
const ul = document.querySelector('ul')

// li에 input의 value 값을 넣어 화면에 보여준다.
const createToDo = toDo => {
  const li = document.createElement('li')
  li.innerText = toDo
  ul.appendChild(li)
}

// 폼을 제출하면 input을 비우고, createToDo 함수를 실행한다.
const onSubmit = e => {
  e.preventDefault()
  const toDo = input.value
  input.value = ''
  createToDo(toDo)
}

form.addEventListener('submit', onSubmit)

 

문제점

데이터를 저장하는 것이 아니라 단순히 innerText를 통해 input.value의 내용을 화면에 보여주는 것이다.

새로고침 시, 데이터가 날아간다.

 


2. 리덕스로 투두 리스트 만들기

  • index.html
<body>
    <h1>To dos</h1>

    <form>
        <input type="text">
        <button>Confirm</button>
    </form>

    <ul></ul>
</body>

 

  • index.js

state는 read-only 이기 때문에 직접 state를 수정하면 안 된다.

store의 state를 수정할 수 있는 유일한 방법은 action을 보내는 것이다.

state를 mutate 하는 것이 아니라, 새로운 state를 return 해야 한다. ex) push, pop을 통해서 배열을 직접 수정하면 안 된다.

import {createStore} from 'redux'

// html 태그 선택
const form = document.querySelector('form')
const input = document.querySelector('input')
const ul = document.querySelector('ul')

const ADD_TODO = "ADD_TODO"
const DELETE_TODO = "DELETE_TODO"

// 2. 리듀서 만들기
const reducer = (state = [], action) => {
  // 3. 액션 만들기
  switch(action.type) {
    case ADD_TODO:
      return [{ id: Date.now(), text: action.text }, ...state] // state.push(action.text) X
    case DELETE_TODO:
      return state.filter(toDo => toDo.id !== parseInt(action.id)) // filter(): 조건에 만족하는 리스트들을 새로운 배열로 return
    default:
      return state
  }
}

// 1. 스토어 만들기
const store = createStore(reducer)

// 투두 리스트 추가하기
const addToDo = text => {
  return {
    type: ADD_TODO,
    text
  }
}

// 투두 리스트 삭제하기
const deleteToDo = id => {
  return {
    type: DELETE_TODO,
    id
  }
}

// 4. 디스페치 만들기
const dispatchAddToDo = text => {
  store.dispatch(addToDo(text))
}

const dispatchDeleteToDo = e => {
  const id = parseInt(e.target.parentNode.id)
  store.dispatch(deleteToDo(id))
}

// 5. 이벤트 함수 만들기
const paintToDos = () => {
  const toDos = store.getState()

  // ul을 빈 값으로 만든 다음에 li를 추가시킨다. (새로운 return 값을 등록해야 하기 때문에 기존에 등록된 내용을 비운다.)
  ul.innerHTML = ''

  toDos.forEach(toDo => {
    const li = document.createElement('li')
    const btn = document.createElement('button')

    btn.innerText = 'DEL'
    btn.addEventListener('click', dispatchDeleteToDo) // 디스패치 실행

    li.id = toDo.id
    li.innerText = toDo.text

    li.appendChild(btn)
    ul.appendChild(li)
  })
}

// paintToDos의 변화를 감지한다.
store.subscribe(paintToDos)

// 5. 이벤트 함수 만들기
const onSubmit = e => {
  e.preventDefault()
  const toDo = input.value
  input.value = ''
  dispatchAddToDo(toDo) // 디스패치 실행
}

form.addEventListener('submit', onSubmit)

+ Recent posts