UI를 바꾸긴 하지만 데이터는 없는 상태 (todolist저장 불가능)
<!DOCTYPE html>
<html lang="en">
<head>
<!--중략-->
<title>Vanilla Redux</title>
</head>
<body>
<h1>To Dos</h1>
<form>
<input type="text" placeholder="Write to do" />
<button>Add</button>
</form>
<ul></ul>
</body>
</html>
const form = document.querySelector("form");
const input = document.querySelector("input");
const ul = document.querySelector("ul");
const createToDo = toDo => {
const li = document.createElement("li");
li.innerText = toDo;
ul.appendChild(li);
};
const onSubmit = e => {
e.preventDefault();
const toDo = input.value;
input.value = "";
createToDo(toDo);
};
form.addEventListener("submit", onSubmit);
import { legacy_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";
// state에 todo내용을 넣을 빈 배열을 준다.
const reducer = (state = [], action) => {
switch (action.type) {
case ADD_TODO:
return [];
case DELETE_TODO:
return [];
default:
return state;
}
};
const store = legacy_createStore(reducer);
const onSubmit = (e) => {
e.preventDefault();
const toDo = input.value;
input.value = "";
// dispatch로 toDo를 함께 보내준다.
store.dispatch({ type: ADD_TODO, text: toDo });
};
form.addEventListener("submit", onSubmit);
관련 내용은 다음 챕터에서...
action
을 보내는 방법뿐이다.Array.prototype.push()
대신에 전개구문을 사용한다. (ES6 spread)
myFunction(...iterableObj)
import { legacy_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";
// *NEVER MUTATE STATE*
const reducer = (state = [], action) => {
switch (action.type) {
case ADD_TODO:
// 전개구문 사용
return [...state, { text: action.text, id: action.id }];
case DELETE_TODO:
return [];
default:
return state;
}
};
const store = legacy_createStore(reducer);
const onSubmit = (e) => {
e.preventDefault();
const toDo = input.value;
input.value = "";
// 다음 챕터에서 코드 개선
store.dispatch({ type: ADD_TODO, text: toDo, id: Date.now() });
};
form.addEventListener("submit", onSubmit);
🛠️참고) 강의에서는 reducer의 case ADD_TODO에서 다음과 같이 Date.now()를 직접 넣어 사용하고 있다.
const reducer = (state = [], action) => { switch (action.type) { case ADD_TODO: return [...state, { text: action.text, id: Date.now() }];
하지만 공식문서에서는 reducer 안에서
Date.now()
를 쓰지 않길 권장하고 있기 때문에 코드를 수정하였다.
참고 자료 : 노마드코더 강의 wodud2920님 댓글
import { legacy_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";
// 코드 최적화: action만을 return하는 함수
// 주로 reducer 위쪽에 배치 함
const addToDo = (text) => {
return { type: ADD_TODO, text, id: Date.now() };
};
const deleteToDo = (id) => {
return { type: DELETE_TODO, id };
};
// *NEVER MUTATE STATE*
const reducer = (state = [], action) => {
switch (action.type) {
case ADD_TODO:
return [{ text: action.text, id: action.id }, ...state];
case DELETE_TODO:
return [];
default:
return state;
}
};
const store = legacy_createStore(reducer);
store.subscribe(() => console.log(store.getState()));
// 코드 최적화: 오로지 action을 dispatch 하기 위한 함수
const dispatchAddToDo = (text) => {
store.dispatch(addToDo(text));
};
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.innerText = "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)
Array.prototype.splice()
대신에 filter을 사용한다.
Array.prototype.filter()
// 생략 ...
case ADD_TODO:
return [{ text: action.text, id: action.id }, ...state];
case DELETE_TODO:
return state.filter((toDo) => toDo.id !== action.id);
default:
return state;
}
// ...중략...
const dispatchAddToDo = (text) => {
store.dispatch(addToDo(text));
};
const dispatchDeleteToDo = (e) => {
const id = parseInt(e.target.parentNode.id);
store.dispatch(deleteToDo(id));
};
// ... 생략
출처 : 노마드코더 - 초보자를 위한 리덕스 101