#2.0 Vanilla ToDo
Vanilla JS > To Do ๋ฆฌ์คํธ๋ฅผ ์์ฑ, ํ๋์ฉ ์ถ๊ฐํ๋ ๊ธฐ๋ฅ
Reduxํ
state ์ค์ , ๊ฐ๋จํ reducer ์์ฑ(์๋X), dispatcher์ ์ฐ๊ฒฐ๊น์ง ํ์ธ
์ฝ๋
import { createStore } from "redux";
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";
const reducer = (state = [], action) => {
switch (action.type) {
case ADD_TODO:
return [];
case DELETE_TODO:
return [];
default:
return state;
}
};
const store = createStore(reducer);
const onSubmit = (e) => {
e.preventDefault();
const toDo = input.value;
input.value = "";
store.dispatch({ type: ADD_TODO, text: toDo });
};
form.addEventListener("submit", onSubmit);
#2.1 State Mutation
ADD ๋ฒํผ ํด๋ฆญ์ state ๊ฐ์ ์ถ๊ฐํ ์ ์๊ฒ ์์ > mutate๊ฐ ์๋ New state๋ฅผ ๋ฆฌํดํ๋ ๋ฐฉ์์ผ๋ก
state๋ single source of truth ์ด๊ณ , read-only ์ด๊ธฐ์ ์ ๋ mutateํ๋ ๋ฐฉ์์ผ๋ก ์์ ํ๋ฉด ์๋๋ค. ์๋ก์ด Object๋ฅผ ๋ฆฌํดํด์ผํจ
์ฝ๋
import { createStore } from "redux";
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";
const reducer = (state = [], action) => {
switch (action.type) {
case ADD_TODO:
return [...state, {text: action.text, id: Date.now()}]; //ES6 SPREAD
case DELETE_TODO:
return [];
default:
return state;
}
};
const store = createStore(reducer);
store.subscribe(() => console.log(store.getState()))
const onSubmit = (e) => {
e.preventDefault();
const toDo = input.value;
input.value = "";
store.dispatch({ type: ADD_TODO, text: toDo });
};
form.addEventListener("submit", onSubmit);
#2.2 Delete To Do
ADD ๋ฒํผ ํด๋ฆญ์ ๋ฆฌ์คํธ ์ถ๊ฐ & DEL ๋ฒํผ ์ถ๊ฐ๋ ์ํ
์์ง DEL ๊ตฌํ์ด ์๋์ ์ ์ฒด๊ฐ ์ญ์ ๋จ
์ฝ๋
import { createStore } from "redux";
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";
const addToDo = (text) => {
return {
type: ADD_TODO,
text,
};
};
const deleteToDo = (id) => {
return {
type: DELETE_TODO,
id,
};
};
const reducer = (state = [], action) => {
switch (action.type) {
case ADD_TODO:
return [{ text: action.text, id: Date.now() }, ...state]; //ES6 SPREAD
case DELETE_TODO:
return [];
default:
return state;
}
};
const store = createStore(reducer);
store.subscribe(() => console.log(store.getState()));
const dispatchAddToDo = (text) => {
store.dispatch(addToDo());
};
const dispatchDeleteToDo = (e) => {
const id = e.target.parentNode.id;
store.dispatch(deleteToDo(id));
};
const paintToDos = () => {
const toDos = store.getState();
ul.innerHTML = "";
toDos.forEach((toDo) => {
const li = document.createElement("li");
const btn = document.createElement("button");
btn.innerHTML = "DEL";
btn.addEventListener("click", dispatchDeleteToDo);
li.id = toDo.id;
li.innerText = toDo.text;
li.appendChild(btn);
ul.appendChild(li);
});
};
store.subscribe(paintToDos);
const onSubmit = (e) => {
e.preventDefault();
const toDo = input.value;
input.value = "";
dispatchAddToDo(toDo);
};
form.addEventListener("submit", onSubmit);
#2.3 Delete To Do part Two
state๋ฅผ filter๋ก ์ ๋ฆฌํด Delete ๊ตฌํ
Do NOT Mutate ! return NEW STATE !!
์์ฑ ์ฝ๋
import { createStore } from "redux";
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";
const addToDo = (text) => {
return {
type: ADD_TODO,
text,
};
};
const deleteToDo = (id) => {
return {
type: DELETE_TODO,
id,
};
};
const reducer = (state = [], action) => {
switch (action.type) {
case ADD_TODO:
return [{ text: action.text, id: Date.now() }, ...state]; //ES6 SPREAD
case DELETE_TODO: // mutate๊ฐ ๋๋ฉด ์๋๊ธฐ์ slice๋ ์ฌ์ฉํ์ง ๋ง์
return state.filter((toDo) => toDo.id !== action.id);
default:
return state;
}
};
const store = createStore(reducer);
store.subscribe(() => console.log(store.getState()));
const dispatchAddToDo = (text) => {
store.dispatch(addToDo());
};
const dispatchDeleteToDo = (e) => {
const id = parseInt(e.target.parentNode.id);
store.dispatch(deleteToDo(id));
};
const paintToDos = () => {
const toDos = store.getState();
ul.innerHTML = "";
toDos.forEach((toDo) => {
const li = document.createElement("li");
const btn = document.createElement("button");
btn.innerHTML = "DEL";
btn.addEventListener("click", dispatchDeleteToDo);
li.id = toDo.id;
li.innerText = toDo.text;
li.appendChild(btn);
ul.appendChild(li);
});
};
store.subscribe(paintToDos);
const onSubmit = (e) => {
e.preventDefault();
const toDo = input.value;
input.value = "";
dispatchAddToDo(toDo);
};
form.addEventListener("submit", onSubmit);
#2.4 Conclusions
fuction์ ์ฌ์ฉํด redux ํ๊ฒฝ์ ๊ตฌ์ฑํ๋ค. action์ dispatchํ๋ fn reducer์ ๋ณด๋ผ object๋ฅผ returnํ๋ fn +a
Do Not Mutate !! Return New State !!! ์ฝ๋์คํ
์ด์ธ ์์ ํ์ตํ ๋ด์ฉ๊ณผ ๊ฐ์ฅ ํฐ ์ฐจ์ด๋ฅผ ๋ณด์ด๋ ๊ตฌ๊ฐ์ด๋ค. ๊ฐ์ ๋ด๋ด ์ด ๋ถ๋ถ์ ๊ฐ์กฐํ๋ฉฐ ๊ธฐ์กด์ ์ํ๋ฅผ ๋ณ๊ฒฝํ๋ ๊ฒ์ด ์๋ ์๋ก์ด ์ํ๋ฅผ ์ ์ธํ๋ ๊ฒ์์ ๊ฐ์ธ์์ผฐ๋ค.