코로 넘어져도 헤딩만 하면 그만
Redux 기초 노마드 코더 정리(2) 본문
바닐라 자바스크립트로 간단한 투두 리스트 추가 감소를 만들어보는 실습이다.
add 버튼을 눌러 추가된 리스트들을 관리해주기 위해서 리덕스를 사용하기로 하였다. 우선 store를 만들고 적절한 액션 타입 별로 분기된 reducer도 만들었다. 이후 submit이 일어날 때 불러지는 함수에서, dispatch를 통해 action을 넘겨준다. (type명 외에도 들어온 text도 함께 준다.)
<body>
<h1>To Dos</h1>
<form id="form">
<input type="text" placeholder = "Write to do" id="input">
<button>Add</button>
</form>
<ul>
</ul>
</body>
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) => {
console.log(action)
switch(action.type){
case ADD_TODO:
return [];
case DELETE_TODO:
return [];
default:
return state;
}
}
const store = createStore(reducer);
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 = "";
store.dispatch({type: ADD_TODO, text:toDo})
}
form.addEventListener("submit", onSubmit)
여기서 리덕스를 다룰 때 주의해야 할 점
1) state는 READ ONLY다. store를 수정할 수 있는 유일한 방법은 action을 보내기 뿐이다.
2) state를 mutate하지 말아야 한다. mutate할 게 아니라 새 object를 리턴해야 한다. 수정 불가, 새 state 리턴.
const reducer = (state = [], action) => {
switch(action.type){
case ADD_TODO:
//여기서 절대 push해서 mutate하지 않도록 한다. 새 객체를 만들어야 함.
return [...state, {text: action.text, id:Date.now()}];
//spread연산자로 복제
//Date.now()로 아이디를 만들어줄 수 있다.
case DELETE_TODO:
return [];
default:
return state;
}
}
const store = createStore(reducer);
store.subscribe(()=>console.log(store.getState()))
이제 여기서 슬슬 dispatch 작업이 들어간다.
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
}
}
//보통 이런 식으로 action만 리턴하는 놈들을 따로 빼주곤 함
const reducer = (state = [], action) => {
switch(action.type){
case ADD_TODO:
return [{text: action.text, id:Date.now()}, ...state];
case DELETE_TODO:
return [];
default:
return state;
}
}
const store = createStore(reducer);
store.subscribe(()=>console.log(store.getState()))
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 createTodo = toDo => {
const li = document.createElement("li");
li.innerText = toDo;
ul.appendChild(li);
}
const onSubmit = e => {
e.preventDefault();
const toDo = input.value;
input.value = "";
addToDo(toDo);
}
form.addEventListener("submit", onSubmit)
그럼 이제 어떻게 dispatch를 써서 리스트를 delete할 수 있을까?
흔히 하는대로 splice를 쓰면 원본이 아예 바뀌어버린다. mutate는 절대 하면 안 되기 때문에 새 array를 리턴해야 한다. 그렇다면 filter을 쓰는 게 좋다. filter은 새로운 array를 만들어준다!
const reducer = (state = [], action) => {
switch(action.type){
case ADD_TODO:
//여기서 절대 push해서 mutate하지 않도록 한다. 새 객체를 만들어야 함.
return [{text: action.text, id:Date.now()}, ...state];
//spread연산자로 복제
//Date.now()로 아이디를 만들어줄 수 있다.
case DELETE_TODO:
return state.filter(toDo => toDo !== action.id);
//여기서 filter조건을 통해 제외한 것만 불러온다.
default:
return state;
}
}
remove하고있는 게 아니라, filter을 통해 원하는 요소를 제외한 새 state를 만들고 있다는 사실을 늘 기억해야 한다.
mutate 금지! 직접 변경 금지!
'CODE STATES 44' 카테고리의 다른 글
"Cannot read properties of undefined (reading 'pathname')" 에러 (0) | 2023.05.31 |
---|---|
Typescript 맛봄 (1) (0) | 2023.05.30 |
Redux 기초 노마드 코더 정리(1) (0) | 2023.05.28 |
rfce 네 글자로 컴포넌트 기본 세팅: 익스텐션 추천 (0) | 2023.05.28 |
Typescript 들어가기 전 주말공부 (0) | 2023.05.28 |
Comments