Redux | NomardCoder
- 기본적으로 javascript application들의 state를 관리하는 방법
- react와 redux는 별개임 (vue, angular, js 등 원하는 곳에서 다 사용가능)
**수업진행방식**
1) redux와 vanilla javascript
2) redux와react (react-redux)
1. redux없이 vanillaJS
+ ) vanillaJS를 redux로 바꾸기
2. redux없이 react
+) react를 redux로 바꾸기 (react-redux)
- redux가 왜 만들어졌고, 왜 redux를 사용해야하는지 - application을 어떻게 향상시키는지
- redux가 필요한 이유를 알기위해, redux없이 application을 실행해보고 redux에 그 아이디어를 더해보는 방식으로 진행할 것
* Pure Redux : Counter
1. redux없이 vanilla JS - count 만들기
const add = document.querySelector("#add");
const minus = document.querySelector("#minus");
const number = document.querySelector("p");
let count = 0;
number.innerHTML = count;
const handle = () => {
number.innerHTML = count;
};
const handleAdd = () => {
count = count + 1;
handle();
};
const handleMinus = () => {
count = count - 1;
handle();
};
add.addEventListener("click", handleAdd);
minus.addEventListener("click", handleMinus);
↓
- redux를 사용하기 위해서 npm install redux 명령어 실행
- redux에서 create store -> import하기 import { createStore } from 'redux';
store은 나의 data를 넣는 곳이다 = 나의 state (=application에서 바뀌는 data)
=> redux는 나의 data를 관리하는데 도와주는 역할을 하기 위해 만들어짐
import { createStore } from "redux";
const reducer = () => {};
//store만들기
const store = createStore(reducer);
- reducer은 함수고, 나의 data를 modify함 (count를 plus하거나 minus하는 것)
- reducer의 첫번쨰 인자는 state(스토어의 이전상태), 두번쨰 인자는 action(객체)을 받는다
import { createStore } from "redux";
const countModifier = () => {
return "hello";
};
//store만들기
const countStore = createStore(countModifier);
console.log(countStore);
- store 출력시 아래와 같음
import { createStore } from "redux";
const countModifier = (count = 0) => {
return count;
};
//store만들기
const countStore = createStore(countModifier);
console.log(countStore.getState());
// 0
정리 - createStore은 store을 create하고, store은 data를 저장하는 곳
- store을 만든다면 store에 countModifier을 줘야한다(redux에서는 reducer라고 불리움)
- default로 data modifier은 현재의 state와 함께 불려짐 (count=0)
2. 어떻게 count를 modify하는지 - action
- action은 redux에서 function을 부를때 쓰는 두번째 parameter or argument이다
import { createStore } from "redux";
const countModifier = (count = 0, action) => {
if (action.type === "add") {
return count + 1;
} else if (action.type === "minus") {
return count - 1;
} else {
return count;
}
};
//store만들기
const countStore = createStore(countModifier);
countStore.dispatch({ type: "add" });
countStore.dispatch({ type: "add" });
countStore.dispatch({ type: "add" });
countStore.dispatch({ type: "add" });
countStore.dispatch({ type: "minus" });
countStore.dispatch({ type: "minus" });
console.log(countStore.getState());
//2
3. subscription
import { createStore } from "redux";
const add = document.querySelector("#add");
const minus = document.querySelector("#minus");
const number = document.querySelector("p");
number.innerHTML = 0;
//reducer
const countModifier = (count = 0, action) => {
console.log(count, action);
if (action.type === "add") {
return count + 1;
} else if (action.type === "minus") {
return count - 1;
} else {
return count;
}
};
//store
const countStore = createStore(countModifier);
//subscribe
const onChange = () => {
//getState
number.innerHTML = countStore.getState();
};
countStore.subscribe(onChange);
//dispatch
const handleAdd = () => {
countStore.dispatch({ type: "add" });
};
const handleMinus = () => {
countStore.dispatch({ type: "minus" });
};
add.addEventListener("click", handleAdd);
minus.addEventListener("click", handleMinus);
dispatch(action) = store과 communication하는 역할 (add, minus)
(action - 변경할 내용 object / 따로 action 함수를 만들어서 dispatch에 넣는것이 코드 최적화에 좋음)
subscribe = store을 subscribe (쉽게말해 변화를 감지)
getState = initial 출력 (변화된 count를 출력)
Recap
- countModifier은 현재상태의 application과 함께 불려지는 function (count = 0)
- +action과 함께 불려짐, action은 countModifier소통하는 방법
- countModifier가 return하는 것은 (= reducer이 return하는 것) = apllication의 state가 됨
=> reducer은 current state와 action이 함께 불려진다!
- reducer에게 action을 보내려면? -> dispatch를 사용해서 보냄 (action은 object이어야함, 무조건 type이 있어야함(string X))
- change의 변화를 감지하고 싶으면? -> subscribe하기
Refactoring
import { createStore } from "redux";
const add = document.querySelector("#add");
const minus = document.querySelector("#minus");
const number = document.querySelector("p");
number.innerHTML = 0;
const ADD = "add";
const MINUS = "minus";
//reducer
const countModifier = (count = 0, action) => {
switch (action.type) {
case ADD:
return count + 1;
case MINUS:
return count - 1;
default:
return count;
}
};
//store
const countStore = createStore(countModifier);
//subscribe
const onChange = () => {
//getState
number.innerHTML = countStore.getState();
};
countStore.subscribe(onChange);
//dispatch
const handleAdd = () => {
countStore.dispatch({ type: ADD });
};
const handleMinus = () => {
countStore.dispatch({ type: MINUS });
};
add.addEventListener("click", handleAdd);
minus.addEventListener("click", handleMinus);
- if else문 -> switch문으로 변경
- 그냥 string을 바로 사용하기 보다, 실수의 위험을 줄이기 위해 constant변수를 사용하자(오류를 쉽게 찾을 수 있음)
* Pure Redux : To Do List
1. redux없이 vanillaJS - toDoList
const form = document.querySelector("form");
const input = document.querySelector("input");
const ul = document.querySelector("ul");
const paintToDo = (text) => {
const li = document.createElement("li");
ul.appendChild(li);
li.innerHTML = text;
};
const handleSubmit = (event) => {
event.preventDefault();
const todo = input.value;
input.value = "";
paintToDo(todo);
};
form.addEventListener("submit", handleSubmit);
2. redux로 상태 변화하기
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 DEL_TODO = "DEL_TODO";
const reducer = (state = [], action) => {
switch (action.type) {
case ADD_TODO:
return [...state, { text: action }];
case DEL_TODO:
return [];
default:
return state;
}
};
const store = createStore(reducer);
store.subscribe(() => console.log(store.getState()));
const handleSubmit = (event) => {
event.preventDefault();
const todo = input.value;
input.value = "";
store.dispatch({ type: ADD_TODO, text: todo });
};
form.addEventListener("submit", handleSubmit);
- state.push() -> 이런식으로 mutation을 사용하면 안됨, 상태를 수정하는 것이 아니라 새로운 것을 return하기
3. deletToDo
const deletToDo = (event) => {
const id = event.target.parentNode.id;
store.dispatch({ tyep: DEL_TODO, id });
};
//reducer
const reducer = (state = [], action) => {
switch (action.type) {
case ADD_TODO:
return [...state, { text: action.text, id: Date.now() }];
case DEL_TODO:
return state.filter((toDo) => toDo.id !== action.id);
default:
return state;
}
};
↓ 코드 최적화 ------------------------------------------------------------------------
const deletToDo = (id) => {
return {
type: DEL_TODO,
id,
};
};
//reducer
const reducer = (state = [], action) => {
switch (action.type) {
case ADD_TODO:
return [...state, { text: action.text, id: Date.now() }];
case DEL_TODO:
return state.filter((toDo) => toDo.id !== action.id);
default:
return state;
}
};
const dispatchDeletToDo = (event) => {
const id = parseInt(event.target.parentNode.id);
store.dispatch(deletToDo(id));
};
- 코드 최적화를 위해 코드를 분리할 수 있다 - 보통 reducer 위에 action 함수를 만듦
- filter 사용으로 state mutation 사용하지 말고, 새로운 배열 return
'Redux' 카테고리의 다른 글
Redux Toolkit (0) | 2021.05.05 |
---|---|
[Redux 강의노트] Redux Middleware | redux-saga (0) | 2021.01.13 |
[Redux 강의노트] Redux Middleware | logger, thunk (0) | 2021.01.09 |
[Redux강의노트] Redux (0) | 2021.01.03 |
React → Redux | Redux 101 (2/2) (0) | 2020.11.24 |