결과 화면


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)

결과 화면

Plus 버튼을 누르면 숫자가 1 증가하고, Minus 버튼을 누르면 숫자가 1 감소한다.


1. 바닐라 자바스크립트로 카운터 만들기

  • index.html
<body>
    <button id="minus">Minus</button>
    <span id="number"></span>
    <button id="plus">Plus</button>
</body>

 

  • index.js
// html 태그 선택
const plus = document.getElementById('plus')
const minus = document.getElementById('minus')
const number = document.getElementById('number')

// 초기값
let count = 0

// html 화면에 초기값 count 보여주기
number.innerText = count

// count가 변할 때 마다 화면에 보여주기
const updateText = () => {
  number.innerText = count
}

// count +1
const handlePlus = () => {
  count++
  updateText()
}

// count -1
const handleMinus = () => {
  count--
  updateText()
}

// 버튼 클릭 이벤트
plus.addEventListener('click', handlePlus)
minus.addEventListener('click', handleMinus)

 


※ 리덕스 기본 개념

  • store

data를 저장하는 곳이다.

import { createStore } from 'redux'
const store = createStore(reducer)

 

  • state(상태)

변경이 필요한 data이다.

 

  • reducre

state를 변경하는 function(함수)이다.

reducer의 return 값이 state가 된다.

const reducer = (state, action) => {}

 

  • action

reducer의 두번째 파라미터 값이다.

action을 통해서만 state를 변경할 수 있다.

action은 object(객체)타입만 가능하고, 그 key 값은 type만 가능하다. (action.type)

공식문서에 따르면 if문 보다는 switch문이랑 더 자주 사용된다.

 

  • dispatch

reducer에 action을 보내는 방법이다.

dispatch를 통해서만 action을 실행시킬 수 있다.

현재 이벤트를 발생시키는 함수라고 볼 수 있다.

store.dispatch({type: 액션이름})

 

  • subscribe

store 안에 있는 변화를 감지한다.

store.subscribe(함수호출)

 


2. 리덕스로 카운터 만들기

yarn add redux 또는 npm install redux

 

  • index.html
<body>
    <button id="plus">Plus</button>
    <span id="number"></span>
    <button id="minus">Minus</button>
</body>

 

  • index.js
import { createStore } from 'redux'

// html 태그 선택
const plus = document.getElementById('plus')
const minus = document.getElementById('minus')
const number = document.getElementById('number')

// 초기값
number.innerText = 0

// string을 직접 사용하기 보다는 변수로 만들어서 사용하는 것이 오타 등의 에러를 발견할 수 있어 효율적이다.
const ADD = 'ADD'
const MINUS = 'MINUS'

// 2. reducer(변수 이름은 자유)를 만든다.
const reduceCountModifier = (count = 0, action) => {
  // 3. action을 만든다.
  switch (action.type) {
    case ADD:
      return count + 1
    case MINUS:
      return count -1
    default:
      return count
  }
}

// 1. store를 만든다.
const countStore = createStore(reduceCountModifier)

// store 안에 있는 state를 가지고 온다.
const onChange = () => {
  number.innerText = countStore.getState()
}

// store 안에 있는 state의 변화를 감지한다.
countStore.subscribe(onChange)

// 4. dispatch를 만든다.
const handlePlus = () => {
  countStore.dispatch({type: ADD})
}
const handleMinus = () => {
  countStore.dispatch({type: MINUS})
}

// 클릭 이벤트
plus.addEventListener('click', handlePlus)
minus.addEventListener('click', handleMinus)

리덕스는 자바스크립트 앱을 위한 예측 가능한 상태(state) 컨테이너이다.

리덕스는 자바스크립트를 사용할 수 있다면 바닐라 자바스크립트, 리액트, 뷰, 앵귤러 등 여러 환경에서 함께 사용할 수 있다.

(리액트와 많이 사용하긴 하지만, 리액트를 위한 전용 라이브러리가 아니다.)

 

1. 깃허브 레포지토리 만들기

https://github.com/heejae0811/vanilla-redux

 

2. npx create-react-app vanilla-redux(레포이름)

 

3. 불필요한 파일 삭제하기

+ Recent posts