지금까지 RN 프로젝트를 해오면서, 짧은 개발기간을 핑계로 많은 상태관리 라이브러리가 있으면서
익숙하던 redux를 항상 고집해왔다.
zustand와 mobx도 실무에서 많이 사용하는 걸로 알고있는데
항상 무엇인가 가벼운(?) 프로젝트에서 많이 사용한다는 잘못된 선입견이 생겨서인지
신규 프로젝트를 구상할때 항상 redux / asyncstorage / persist-store 들로 상태관리를 했다.
성장하지 않는 느낌이 들어서, 이번에 짧은 개발기간임에도 불구하고, 이꽉물고 새로운 상태관리를 적용해보려했다.
결과적으로 말하자면 redux를 사용할때보다 보일러 플레이트가 현저히 줄어서, 코드 치기가 쉬웠다.
이번 글에선 react-native cli로 생성한 프로젝트에 mobx 를 적용하는 간단한 설명을 메모해 두려고한다.
항상 새로운 라이브러리를 쓴다는건 신나는 일이고, 결국엔 거의 비슷한 로직으로 돌아간다는게 참 재밌는거 같다.
당연히 mobx도, redux처럼 여러개의 store를 사용할수있고(redux에서 여러개의 reducer를 root reducer로 합치는 것과 동일)
하나의 store에 여러값을 저장 할 수 있다.
yarn add mobx
yarn add mobx-react
일단 mobx 와 mobx-react 를 프로젝트에 import 해준다
( mobx-react-lite를 임포트 해주라는 글들도 있지만, mobx-react-lite 내가 적용할때는 babel쪽 syntax에러가 많이 발생해서
mobx-lite를 import해 줬다.)
기본 구조
hooks/useRootData.js 는 mobx를 쓰는 hook으로
소스코드는
import {useObserver} from 'mobx-react';
import React, {useContext} from 'react';
import {storesContext} from '../utils/context';
export const useStoreData = (context, storeSelector, dataSelector) => {
const value = useContext(context);
if (!value) {
throw new Error('No store');
}
const store = storeSelector(value);
return useObserver(() => {
return dataSelector(store);
});
};
export default dataSelector => {
return useStoreData(storesContext, contextData => contextData, dataSelector);
};
import {observable, runInAction} from 'mobx';
const createStore = () => {
const anotherStore = {
anotherKey: observable.box('anotherKey'),
changeAnotherKey: data =>
runInAction(() => anotherStore.anotherKey.set(data)),
};
return anotherStore;
};
const anotherStore = createStore();
export default anotherStore;
import {observable, runInAction} from 'mobx';
const createStore = () => {
const loginInfoStore = {
loginInfo: observable.box('userName'),
changeLoginInfo: data =>
runInAction(() => loginInfoStore.loginInfo.set(data)),
connect: observable.box(true),
changeConnect: data => runInAction(() => loginInfoStore.connect.set(data)),
};
return loginInfoStore;
};
const store = createStore();
export default store;
import loginInfoStore from './loginInfoStore';
import anotherStore from './anotherStore';
const createRootStore = () => {
return {
loginInfoStore,
anotherStore,
};
};
export default createRootStore;
import {useLocalObservable} from 'mobx-react';
import React, {createContext} from 'react';
import createRootStore from '../store/index';
export const storesContext = createContext(null);
export const StoreProvider = ({children}) => {
const store = useLocalObservable(createRootStore);
return (
<storesContext.Provider value={store}>{children}</storesContext.Provider>
);
};
이 소스코드들을 두가지 store에 한스토어당 2가지이상을 세팅하는 예제로 사용하면 된다.
상태값을 사용하고 싶은 component에서
const {loginInfo, changeLoginInfo, connect, changeConnect, anotherKey} =
useStoreData(({loginInfoStore, anotherStore}) => ({
loginInfo: loginInfoStore.loginInfo.get(),
changeLoginInfo: loginInfoStore.changeLoginInfo,
connect: loginInfoStore.connect.get(),
changeConnect: loginInfoStore.changeConnect,
anotherKey: anotherStore.anotherKey.get(),
}));
해당 hook으로 state, setState 값을 선언해주고
이런식으로 사용해주면된다.
이번 프로젝트에 mobx의 기본 구조를 적용하면서, 내가 redux-saga / redux-thunk 등의 미들웨어가 mobx에서 어떻게 적용되는지,
mobx의 persist-store적용은 어떻게 하는지 등에 대해 궁금증이 생겼다.
개발은 참 재미있다.