redux 오픈소스 코드를 뜯어서 createStore 직접 구현해보기
프리온보딩 과제 - createStore 최소 구현체 만들기
공식문서를 참고해서 createStore를 직접 구현하는 과제를 주셨다.
Redux를 썼을 때도 RTK로 사용해서 createStore에 무엇이 전달되어야하는지 공식문서를 참고했다.
createStore | Redux API > createStore: creating a core Redux store ko.redux.js.org
Store | Redux API > Store: the core Redux store methods ko.redux.js.org
정리해보면 하나의 store를 만들어주는 함수로 상태를 업데이트해주고 다음 상태를 반환해주는 reducer, 초기 값 preloadedState을 매개변수로 받아서 현재 상태를 반환해주는 getState, reducer를 통한 상태 변경을 시키기 위해 action을 전달하는 dispatch, 마지막으로 dispatch가 발생할 때마다 실행시키는 subscribe(listener)로 구성되어 있다.
redux의 구조 자체를 안다면 더 쉽고 좋은 글들이 많아 사진으로 봐도 충분할 거 같아 단순 링크만 가져왔다
In : preloadedState, reducer
out : getState, dispatch, subscribe
라고 정의할 수 있으며 오픈 소스를 참고하여 만들었다.
// createStore 간단하게 구현해보가
// create Store는 리듀서를 인자로받아 store를 리턴하는 함수이다.
// store는 subscribe(), dispatch(), getState()를 메서드로 가진 객체다.
interface Action {
type: "ADD_TODO";
text: string;
}
function todoList(state: any = [], action: Action) {
switch (action.type) {
case "ADD_TODO":
return state.concat([action.text]);
default:
return state;
}
}
const createStore = function <S, A>(
reducer: (state: S, action: A) => S,
preloadedState: S
) {
const currentReducer = reducer;
let currentState = preloadedState as S;
let currentListeners: VoidFunction[] | null = [];
let nextListeners = currentListeners;
const getState = function (): S {
return currentState;
};
//상태를 업데이트 해줘야하고 상태를 업데이트 했다면 subscribe에 있는 함수들을 실행시켜준다
const dispatch = function (action: A): A {
currentState = currentReducer(currentState, action);
const listeners = (currentListeners = nextListeners);
if (listeners) listeners.forEach((listener) => listener());
return action;
};
const subscribe = function (listener: VoidFunction) {
// subscribe는 dispatch가 호출될 떄마다 실행되는 함수(정확히는 상태가 변경될때마다 실행됨)
// unsubscribe라는 함수를 반환하며 호출되는 함수를 지울 때 사용
nextListeners.push(listener);
return function unsubscribe() {
const index = nextListeners.indexOf(listener);
nextListeners.splice(index, 1);
currentListeners = null;
};
};
return { getState, dispatch, subscribe };
};
const store = createStore(todoList, []);
console.log(
store.dispatch(
store.dispatch({
type: "ADD_TODO",
text: "Read the docs",
})
)
);
console.log(store.getState());
console.log(store.subscribe(() => {}));
타입 부분을 조금 애먹었는데 하나하나 정의해보니 크게 어렵지 않았다. 오픈 소스로 이루어진 프로젝트 자체를 뜯어본적은 처음이었는데 무슨 동작을 하는지만 확인한다면 구조가 워낙 잘 짜여 있어 어렵지 않게 이해할 수 있을거라고 생각한다.
그런데 action의 타입을 지정해주는 부분은 아직도 헷갈린다