mobX는 워낙 자유로운 라이브러리이므로 React에 적용하는 방법이 굉장히 다양하다.
현재 구축하는 방법은 하나의 방법일 뿐이므로 확장된 시야로 붙여보자 !
mobx-react/package.json
{
"name": "mobx-react-playground",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"dev": "webpack serve --env development"
},
"author": "vicky",
"license": "ISC",
"dependencies": {
"mobx": "^6.1.8", // 추가
"mobx-react": "^7.1.0", // 추가
"react": "^17.0.2",
"react-dom": "^17.0.2"
},
"devDependencies": {
"@babel/core": "^7.12.10",
"@babel/plugin-proposal-class-properties": "^7.12.1",
"@babel/plugin-proposal-decorators": "^7.13.5", // 추가
"@babel/preset-env": "^7.12.11",
"@babel/preset-react": "^7.12.10",
"@pmmmwh/react-refresh-webpack-plugin": "^0.4.3",
"babel-loader": "^8.2.2",
"react-refresh": "^0.9.0",
"webpack": "^5.16.0",
"webpack-cli": "^4.4.0",
"webpack-dev-server": "^3.11.2"
}
}
mobx-react/webpack.config.js
module.exports = {
// settings..
module: {
rules: [
{
test: /\\.jsx?$/,
loader: "babel-loader",
options: {
presets: [
// settings..
],
plugins: [
["@babel/plugin-proposal-decorators", { legacy: true }], // 추가
["@babel/plugin-proposal-class-properties", { loose: true }], // 추가
"react-refresh/babel",
],
},
exclude: path.join(__dirname, "node_modules"),
},
],
},
// settings..
};
위와 같이 mobX를 위한 프로젝트 설정이 끝나면 가장 먼저 App.js를 만들어준다. 기존 프로젝트에서 진행했던 애플리케이션을 mobX로 적용해보는 작업을 진행할 것임
mobx-react/App.js
import React, { Component } from 'react';
import { observable } from 'mobx';
import { observer } from 'mobx-react';
import { userStore, postStore } from './store'; // 2. store 데이터 호출
@observer // 1. class 컴포넌트에서 사용하는 decorator(Mobx6부터 사용하지 않는다.)
class App extends Component {
onLogIn = () => {};
onLogOut = () => {};
onChangeName = e => (this.state.name = e.target.value);
onChangePassword = e => (this.state.password = e.target.value);
render() {
return (
<div>
{userStore.isLoggingIn ? (
<div>로그인 중입니다.</div>
) : userStore.data ? (
<div>{userStore.data.nickname}</div>
) : (
'로그인 해주세요'
)}
{!userStore.data ? (
<button onClick={this.onLogIn}>로그인</button>
) : (
<button onClick={this.onLogout}>로그아웃</button>
)}
<div>{postStore.data.length}</div>
<div>
<input value={this.state.name} onChange={this.onChangeName} />
<input
value={this.state.password}
type="password"
onChange={this.onChangePassword}
/>
</div>
</div>
);
}
}
export default App;
@observer
@
은 아직 실험적인 단계이므로 섣불리 사용해선 안된다. 또한 사용하기 전에 tsconfig.json이나 jsconfig.json에서 experimentalDecorators
를 활성화 처리를 해주는 방법이나 vsCode 등의 기본 설정에서 JS/TS 설정 중 Implicit Project Config: Experimental Decorators
를 활성화 해주어야 문법 오류 없이 적용된다. ⇒ MobX6에서 데코레이터가 사라졌으므로 앞으로 사용하지 않는다)mobx-react/store.js
const { observable } = require('mobx');
// 1. 일반 객체 리터럴 - obsevable HOC
const userStore = observable({
isLoggingIn: false,
data: null,
logIn(data) {
this.isLoggingIn = true;
setTimeout(() => {
this.data = data;
this.isLoggingIn = false;
postStore.data.push(1); // 2. redux에 비해 편한 점
}, 2000);
},
logOut() {
this.data = null;
},
});
const postStore = observable({
data: [],
addPost(data) {
this.data.push(data);
},
});
export { userStore, postStore };
실제 App 컴포넌트에서 로그인 버튼 클릭 시 2초 후 로그인이 되면서 postData가 1씩 증가하는 것을 볼 수 있다. store에서 userData 내 logIn 동작 처리 시 postData의 값들도 한번에 처리할 수 있음을 보여주는 예시이다
Mobx에서 Model Layer를 구현하는데 순수 Class형태로 구현이 가능하지만 Model 라이브러리를 사용하면 라이브러리에서 제공하는 기능들을 사용할 수 있음