index.html
<body>
<h1>To Dos</h1>
<form>
<input type="text" placeholder="Write to do" />
<button>Add</button>
</form>
<ul></ul>
</body>
index.js
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);
1. createStore, reducer의 기본적인 구성 구현
import { createStore } from "redux";
const reducer = ( state = [], action ) => {
switch (action.type) {
case "ADD_TODO":
return [];
case "DELETE_TODO":
return [];
case default:
return state;
};
};
const store = createStore(reducer);
2. createToDo
함수를 dispatch
로 대체하기
const addToDo = (toDo) => {
store.dispatch({ type: "ADD_TODO", text: toDo });
}
const onSubmit = () => {
e.preventDefault();
const toDo = input.value;
input.value = "";
addToDo(toDo);
}
3. action creator 함수 만들기
const ADD_TODO = "ADD_TODO";
const DELETE_TODO = "DELETE_TODO";
//functions : action creators
const addToDo = text => return { type: ADD_TODO, text };
const deleteToDo = id => return { type: DELETE_TODO, id };
//...
//functions for only dispatch
const dispatchAddToDo = (text) => {
store.dispatch(addToDo(text));
};
const dispatchDeleteToDo = (e) => {
const id = parseInt(e.target.parentNode.id);
store.dispatch(deleteToDo(id));
};
4. dispatch 함수 완성하기
중요) state를 변형하지 않고, 새로운 객체를 생성하여 return 하기
ADD_TODO : 입력된 text를 state에 추가하는 기능
→ 입력된 텍스트를 갖는 객체와 state의 모든 객체를 포함하는 배열을 반환
case ADD_TODO:
// **NOT** : return state.push(action.text);
const newTodoObj = { text: action.text, id: Date.now() };
return [newTodoObj, ...state];
DELETE_TODO: 입력된 ID의 객체를 state에서 삭제하는 기능
→ state의 객체 중 입력된 ID와 동일한 ID를 갖는 객체를 제외한 배열을 반환
case DELETE_TODO:
// **NOT** : return state.splice(...)
const filterdObj = state.filter(toDo => toDo.id !== action.id;
return filteredObj;
!! NEVER MUTATE STATE !!
- state는 읽기 전용(read-only) property로, 직접 값을 변경할 수 없다.
- state를 변경하는 유일한 방법은 store로 action을 보내는 것 뿐이다.
- 새로운 state가 될 object를 return하면 됨.
5. state의 변화 감지 시 화면 새로 그리기
toDo li를 새로 그리는 함수 paintToDo
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);
})
};
subscribe
store.subscribe(paintToDos);
index.js
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:
// **NOT** : return state.push(action.text);
const newTodoObj = { text: action.text, id: Date.now() };
return [newTodoObj, ...state];
case DELETE_TODO:
return state.filter(toDo => toDo.id !== action.id);
default:
return state;
}
};
const store = createStore(reducer);
const dispatchAddToDo = (text) => {
store.dispatch(addToDo(text));
};
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.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);