[React] 전역 상태 관리 라이브러리 제작기 (3)
[React] 전역 상태 관리 라이브러리 제작기 (3)
[React] 전역 상태 관리 라이브러리 제작기 (1)
[React] 전역 상태 관리 라이브러리 제작기 (2)
위 포스트에서 작업한 전역 상태 관리 라이브러리에 useReducer
와 같이 reducer
함수를 전달받아서 dispatch
action
으로 상태를 관리하는 구조를 추가하도록 하겠습니다.
Redux의 상태관리
Redux는 아래와 같이 작성해서 상태 관리를 할 수 있습니다.
import { createStore } from 'redux'
function counterReducer(state = { value: 0 }, action) {
switch (action.type) {
case 'counter/incremented':
return { value: state.value + 1 }
case 'counter/decremented':
return { value: state.value - 1 }
default:
return state
}
}
const store = createStore(counterReducer)
store.subscribe(() => console.log(store.getState()))
store.dispatch({ type: 'counter/incremented' }) // {value: 1}
store.dispatch({ type: 'counter/incremented' }) // {value: 2}
store.dispatch({ type: 'counter/decremented' }) // {value: 1}
Redux의 구조와 같이 store
를 생성할 때 reducer
함수를 인자로 전달하도록 작성할 것입니다.
reducer
함수를 사용해 store
를 생성했다면, useGlobalStore
Hook의 반환 값으로 dispatch
를 반환하도록 할 것입니다.
redux 함수
'redux
와 비슷한 구조를 가질 수 있도록 어떻게 해야 할까?' 하는 고민을 정말 많이 했습니다. 구현하는 것은 간단히 했지만, 이렇게 작업하는 것이 정말 효율적인 방법일까? 하는 의문이 들어서 수 차례 수정을 하게 되었네요.
결과적으로는 reducer
함수를 인자로 전달받으면 state
와 dispatch
를 반환하는 함수를 반환하는 redux
함수를 작성하였습니다.
글로 적으니까 뭔가 말 장난처럼 보이는데, 코드를 먼저 살펴보겠습니다.
타입
interface ReducerAction {
type: string;
[key: string]: any;
}
interface ReducerStore<T> {
state: T;
dispatch: DispatchType;
}
export type DispatchType = (action: ReducerAction) => void;
export type ReducerFunction<T> = (state: T, action: ReducerAction) => T;
export type ReducerReturnType<T> = (getState: StoreGetState<T>, setState: StoreSetState<T>) => ReducerStore<T>;
위 타입이 redux
함수에서 사용될 타입입니다.
dispatch
에서 action
은 객체로 이뤄져 있으며 type
키는 필수로 포함되어야 합니다. type
이외의 정보를 dispatch
로 전달해야 할 수 있어서 이를 대응하기 위해 [key: string]: any;
타입을 추가하였습니다.
ReduxStore
는 redux
함수가 반환하는 함수에서 반환하는 타입을 의미합니다.
redux
함수에서는 ReducerReturnType
타입에서 알 수 있듯이 (getState: StoreGetState<T>, setState: StoreSetState<T>) => ReducerStore<T>
타입을 반환하며, createStore
함수에서 getState
와 setState
정보를 넘겨줘서 state
및 dispatch
정보를 얻습니다.
state
를 넘겨주는 이유는 redux
에서 전달받은 값으로 createStore
의 state
에 값을 저장하기 위함입니다.
실제 구현부
const redux = <T = any>(reducer: ReducerFunction<T>, defaultState: T): ReducerReturnType<T> => (
getState,
setState,
): ReducerStore<T> => {
const dispatch = (action: ReducerAction) => {
setState(state => {
return reducer(state, action)
});
};
setState(defaultState);
return { state: getState(), dispatch };
};
타입 부분에서 설명한 것과 같이 redux
함수는 getState
와 setState
를 인자로 받으면서 ReducerStore
타입을 반환하는 함수를 반환합니다.
redux
함수에 넘겨줘야 하는 값은 reducer
함수와 defaultState
두 개의 값이며, 이 반환값을 createStore
에 넘겨주면 createStore
에서 대응을 할 수 있도록 해야 합니다.
dispatch
함수의 경우, action
을 전달받으며, reducer(state, action)
함수를 실행시켜 그 결괏값을 저장합니다. 여기에서 값이 변화하면 react
에서 바로 반응하기 위해 setState
를 통해 값을 수정하는 것을 확인할 수 있습니다.
createStore
현재 createStore
함수는 인자로 전달받은 값을 state
에 저장합니다. redux
함수의 목적은 함수를 store
의 state
에 저장하는 것이 아닌, dispatch
를 이용해서 상태관리를 하는 것이므로 createStore
의 값을 저장하는 부분에 수정이 필요합니다.
createStore
함수의 let state = defaultState;
부분이 아래와 같이 변경되어야 합니다.
if (typeof createState === "function") {
const {dispatch, state: reduceState} = (createState as ReducerReturnType<T>)(getState, setState);
state = reduceState;
return {getState, setState, onChange, dispatch};
} else {
state = createState;
return { getState, setState, onChange };
}
위 코드에서 createState
즉, 인자로 전달받은 값이 함수라면 그 함수에 getState
와 setState
를 인자로 전달해 dispatch
와 state
값을 반환받습니다. 여기서 반환받은 state
값을 store
의 state
에 저장한 뒤, dispatch
를 포함해서 값을 반환합니다.
만약, 함수를 전달받지 못했다면, 이전과 같이 인자로 전달받은 값을 store
의 state
에 저장한 뒤, getState
, setState
, onChange
값을 반환합니다.
useGlobalStore
useReducer
는 배열을 반환하는데, 첫 번째 값으로 state
값을, 두 번째 값으로 이를 수정할 수 있는 dispatch
함수를 반환합니다. 이와 같은 구조로 작업을 진행하려 합니다.
이는 매우 쉬운데, useGlobalStore
의 반환값을 아래와 같이 수정하면 됩니다.
return [ selectedState(store.getState()), store.dispatch || store.setState ];
전달받은 store
값에 dispatch
가 있다면 dispatch
를 반환, dispatch
가 없다면 setState
값을 반환합니다.
추후 업데이트 내용
localStorage
를 이용한 persist
정도를 추가 기능으로 생각하고 있으며, 이 기능 작업이 완료된다면 패키지로 작업해 npm에 배포할 예정입니다.
'Project > JavaScript Project' 카테고리의 다른 글
sagen - 상태 관리 라이브러리 (0) | 2021.02.10 |
---|---|
[React] 전역 상태 관리 라이브러리 제작기 (2) (0) | 2020.12.01 |
[React] 전역 상태 관리 라이브러리 제작기 (1) (0) | 2020.11.29 |
댓글
이 글 공유하기
다른 글
-
sagen - 상태 관리 라이브러리
sagen - 상태 관리 라이브러리
2021.02.10 -
[React] 전역 상태 관리 라이브러리 제작기 (2)
[React] 전역 상태 관리 라이브러리 제작기 (2)
2020.12.01 -
[React] 전역 상태 관리 라이브러리 제작기 (1)
[React] 전역 상태 관리 라이브러리 제작기 (1)
2020.11.29