[2019.08.14] Mobx State Tree(mst) 사용법
Mobx State Tree는 Mobx에서 조금 더 체계가 잡힌 패러다임....?
Mobx의 type, action 등 구조의 자유도가 높았다면, mobx state tree는 관련된 것들끼리 tree 구조로 구성하도록 한다.
(설명이 아직은 어렵다..)
# mst를 사용하기 위한 환경 세팅
$ npx create-react-app
$ yarn add mobx mobx-react mobx-state-tree
# model 정의
model은 컴포넌트 내에서 사용되는 하나의 store이다.
해당 store 값을 조작하는 함수인 actions. store 변경으로 인해 자동으로 연상되는 (mobx의 computed와 같은)값 views.
위와 같이 하나의 store와 해당 store에 관련된 것들끼리 모여 하나의 모델이라는 구조를 이룬다.
src/models/Invoice.js
import { types } from 'mobx-state-tree';
const Invoice = types.model('Invoice',{
currency: types.string,
is_paid: types.boolean, // 데이터 선언 부분
image: ''
})
// 데이터 조작 부분
.actions(self => ({
markPaid() {
self.is_paid = true;
}
}))
// 데이터 변경으로 연산된 값을 보내줄 부분
.views((self) => ({
status () {
return self.is_paid ? "Paid" : "Not Paid";
}
}))
export default Invoice;
모델을 선언하는 방식은 위 코드와 같다.
우선 데이터 타입과 해당 데이터를 조작할 actions로 구성되어 있다.
데이터 선언 부분을 보면, 데이터 명과 해당 타입을 선언한다. (mst 내의 타입을 정의해주므로 느슨한 타입을 바로 잡아줄 수 있다는 장점이 있다!)
그러나 마지막 데이터인 image를 보면, 타입 선언이 아닌, ' ' 문자열이 들어간 것을 확인할 수 있다.
image와 같이 타입 선언이 아닌 실제 데이터를 넣게되면, 모델이 처음 사용 시 해당 데이터로 초기화 된다. 당연히 초기화가 직접 되므로써, 해당 데이터와 같은 타입으로 자동 선언이 된다.
이 부분은 아래의 model 생성 부분에서 다시 자세하게 알아보도록 하자.
데이터를 조작하는 actions 부분을 보면, self라는 매개변수를 받는다. 이 매개변수는 this와 같으므로, 여기서는 Invoice 자체로 봐도 무방하다.
markPaid()라는 함수를 선언하여, is_paid에 true를 대입하도록 했다.
데이터 변경으로 새로 연산되어 뷰 단에 보여줄 결과 값은, views라는 메소드를 이용한다.
내보낼 각 결과 값을 함수의 리턴 값으로 하여, 나중에 각 컴포넌트는 이 함수를 호출해서 결과 값을 가져온다.
여기서는 status라는 함수를 생성하여 is_paid가 true면 'Paid'를, 아니면 'Not Paid'를 반환하도록 한다.
# model을 생성하여 사용
src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';
import Invoice from './models/Invoice';
// 모델 인스턴스 생성
const invoice = Invoice.create({currency:'name', is_paid:false});
// 모델을 props로 내려줌
ReactDOM.render(<App invoice={invoice}/>, document.getElementById('root'));
serviceWorker.unregister();
리액트의 루트 엔트리인 index.jsDPTJ Invoice 모델을 위 처럼 생성한다.
currency는 string, is_paid는 boolean 타입으로 지정해 주었으므로, 해당 타입에 맞는 데이터가 아니면 에러가 발생하게 된다.
현재 데이터는 {currency: 'name', is_paid: false} 로 초기화를 시켜서 생성하였으므로, 실제로 생성된 Invoice의 value는 아래와 같다.
(모델에는 정의 되어있는 데이터 currency, is_paid를 인스턴스 생성 시에 사용해 주지 않으면 에러가 발생한다.)
{
currency: 'name',
is_paid: false,
image: ''
}
currency, is_paid는 create문으로 생성 시 직접 초기화를 해주었지만, image는 모델 정의를 할 때, ' '라는 image가 초기화 되서 생성되도록 선언을 하였었다.
src/App.js
import React from 'react';
import {observer} from 'mobx-react';
class App extends React.Component {
render() {
const {invoice} = this.props;
return (
<div className="App">
<h1>{invoice.status()}</h1>
<button onClick={invoice.markPaid}>Pay</button>
</div>
)
}
}
export default observer(App);
App 컴포넌트에서는, 실제로 invoice 모델 인스턴스를 사용하게 된다.
button태그에서 클릭 이벤트로, invoice.markPaid 함수가 실행하도록 하였다.
해당 버튼을 클릭하면, 모델 안의 is_paid 값이 true로 변하게 된다.
값이 변경되면, h1태그의 status 출력값도 새로운 출력 값으로 다시 나오게 된다.
(마지막 줄에 App 컴포넌트를 observer 처리를 해주어야만, view단에서 변경된 값이 화면에 보여지게 된다.)
아직 설명할게 많은데..ㅠㅠ
우선 기본적인 mst 개념과 기본 사용법은 여기까지 하고, 다음 글에 좀 더 다뤄보도록 해야겠다.