# #2 PURE REDUX: TO DO LIST

### #2.0 **Vanilla ToDo**

Vanilla JS > To Do 리스트를 작성, 하나씩 추가하는 기능

**Redux화**

state 설정, 간단한 reducer 작성(작동X), dispatcher에 연결까지 확인

* 코드

  ```jsx
  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를 리턴해야함

* 코드

  ```jsx
  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 구현이 안되서 전체가 삭제됨

* 코드

  ```jsx
  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 !!

* 완성 코드

  ```jsx
  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**

1. **fuction**을 사용해 redux 환경을 구성한다. action을 dispatch하는 fn reducer에 보낼 object를 return하는 fn +a
2. **Do Not Mutate !! Return New State !!!** 코드스테이츠에서 학습한 내용과 가장 큰 차이를 보이는 구간이다. 강의 내내 이 부분을 강조하며 기존의 상태를 변경하는 것이 아닌 새로운 상태를 선언하는 것임을 각인시켰다.

***


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://onemorebottlees-organization.gitbook.io/onemorebottlees-til/lecture/nomad-coders/101/2-pure-redux-to-do-list.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
