reducer
에 action에 대해 저장한다.subscribe
메서드를 통해 상태의 변경사항 전달을 확인한다.
subscribe
내에서 store의 상태를 콜백해주는 getState
를 콘솔로 출력한다.dispatch
메서드를 통해 action을 실행해본다.import { createStore } from "./redux";
function reducer(state = { counter: 0 }, action) {
switch (action.type) {
case "inc":
return {
...state,
counter: state.counter + 1
};
default:
return { ...state };
}
}
const store = createStore(reducer);
store.subscribe(() => {
console.log(store.getState()); // { counter: 1 }
});
store.dispatch({
type: "inc"
});
subscribe
, dispatch
, createStore
는 동기적으로 발생하고 있다.
모든 로직이 동기적으로 발생하므로 reducer
는 반드시 순수 함수로 작성되어야 한다.
createStore
→ dispatch
→ subscribe
→ createStore
→ dispatch
→ ...Redux는 동기 함수이므로, 비동기 함수로 상태를 업데이트 할 수 없다.
fetch-user
는 state를 업데이트 할 수 없다.import { createStore } from "./redux";
// setTimeout을 이용한 비동기 함수 api 생성
function api(url, cb) {
setTimeout(() => {
cb({ type: "응답이야", counter: 10 });
}, 2000);
}
function reducer(state = { counter: 0 }, action) {
switch (action.type) {
case "inc":
return {
...state,
counter: state.counter + 1
};
break;
case "fetch-user":
api("/api/v1/users/1", (users) => {
return { ...state, ...users };
});
break;
default:
return { ...state };
}
}
const store = createStore(reducer);
store.subscribe(() => {
console.log(store.getState()); // {}
});
// 비동기 작업.. state 업데이트 불가
store.dispatch({
type: "fetch-user"
});
Redux 내에서 비동기 작업을 처리하기 위해 미들웨어를 이용한다.
먼저 기준 데이터 처리기(redux)는 순수 함수이므로, 변할 수 없는 성질을 가진다.
(데이터(input) → 기준 데이터 처리기 → 정제된 데이터(output) : input → output)
플러그인이나 미들웨어를 이용해 데이터 흐름의 확장성을 넓힐 수 있다
데이터(input) → 미들웨어 → 정제된 데이터(output) → 미들웨어 → 정제된 데이터(output) → ...
그러나 미들웨어는 문법적으로 비동기 코드를 동기 코드처럼 보이게 만드는 것일 뿐, 실제 동기 작업과 비동기 작업을 혼재하여 순서를 보장하도록 만들 수는 없다. 🧐