Mobx

Jinmin Kim·2023년 1월 2일
0

install

npm install mobx mobx-react

1.

state observable

const state = observable({
	test1: 0,
    test2: 1,
    test3: 2,
})

autorun, runInaction

autorun : 어떤 값이 변경되었을때 인식하게 되는것

autorun(() => {
		console.log("change");
	}
)

runInaction: 어떤값을 변경할것이라는것을 명시해주는것

runInaction(() => {
	state.test1 = 1;
    state.test2 = 2;
    state.test3 = 3;
})

이렇게 햇을때에 autorun에는 change가 한번밖에 찍히지 않는데,
runInaction을 쭉 나열했을경우에는 한번만 인식하게된다.

  • Mobx 정리
  1. obsersver, observable, action
import React, { Component } from 'react';
import { observable, action } from 'mobx';
import { observer } from 'mobx-react';

// **** 최하단에 잇던 observer 가 이렇게 위로 올라옵니다.
@observer
class Counter extends Component {
  @observable number = 0;

  @action
  increase = () => {
    this.number++;
  }

  @action
  decrease = () => {
    this.number--;
  }

  render() {
    return (
      <div>
        <h1>{this.number}</h1>
        <button onClick={this.increase}>+1</button>
        <button onClick={this.decrease}>-1</button>
      </div>
    );
  }
}

// **** decorate 는 더 이상 필요 없어집니다.
// decorate(Counter, {
//   number: observable,
//   increase: action,
//   decrease: action
// })

// export default observer(Counter);
// **** observer 는 코드의 상단으로 올라갑니다.
export default Counter;
  1. inject
// **** 함수형태로 파라미터를 전달해주면 특정 값만 받아올 수 있음.
@inject(stores => ({
  number: stores.counter.number,
  increase: stores.counter.increase,
  decrease: stores.counter.decrease,
}))

@action과 @computed 차이

@observable의 변화와 Render

observable 변수가 수정 되면, MobX에 이벤트가 등록 된다 그렇게 차곡차곡 Stack에 쌓이고 하나하나 실행하며, 컴포넌트들을 Render 하는 방식이다. 놀랍게도 한 번의 이벤트 발생에 observable 변수 10개가 변화하면 10번의 랜더 이벤트가 call Stack에 추가 될 것이다.

이전에 페이지 한 번 로딩에 최상단 컴포넌트 render()가 50번 호출 된 적이 있었는데. MobX를 모르고 사용한 탓이다.

물론, DOM의 변경 사항이 없다면 VirtualDOM이 이를 지켜주지만 혹 Render()안에서 연산이 들어간다면 이 연산들은 실행 될 것 이고, 어찌 되었든 상태관리가 없는 것 보다는 심각한 기능 문제를 발생 시킬 수 있다.

MobX observable 변수가 변경 하면 이벤트 실행 목록에 하나씩 쌓이고, Render를 기다리게된다.

@action & @action.bound

  @observable private a = 0;
  @observable private b = 0;
  @observable private c = 0;
  @observable private d = 0;
  @observable private e = 0;
  @observable private f = 0;

  // @action
  set() {
    this.a = 1;
    this.b = 2;
    this.c = 3;
    this.d = 4;
    this.e = 5;
    this.f = 6;
  }

위 예제에서 6개의 이벤트가 생성 된다.
하지만, @action을 사용하면, 이를 하나의 이벤트로 만들 수 있다.

바인딩이 필요한 경우에는 @action.bound를 사용

  1. 일반 @action 사용
  @observable private browserWidth = 0;

  constructor(props: HomePageProps) {
    super(props);

    window.addEventListener("resize", this.setBrowserWidth);
  }

  @action
  setBrowserWidth() {
    this.browserWidth = window.innerWidth;
  }

결과 : 바인딩 되지 않아, 값 변하지 않음.

  1. 공식문서 사용 방법
  @action.bound
  setBrowserWidth() {
    this.browserWidth = window.innerWidth;
  }

결과 : 정상적으로 바인딩이 되고, @action 처리도 진행

@computed

  @computed get BrowserWidth() {
    return this.browserWidth;
  }
  • @computed를 사용하는 이유
  1. @observable 변수에 직접 접근을 막기
  2. @observable 들의 연산이 필요할 때

@computed는무조건 get 함수로 선언해야한다.

사용 Tip!

* 상위 Component에서 아래와 같이 store 값을 내려준다.
 <Provider Store={Store}>
 </Provider>


@inject(stores => ({
    setStore : stores.Store.setStore,
    groupLength : stores.Store.groupLength,
}))

@observer
class Test extends React.Component {



//...

const {setStore, groupLength} = this.props;
와 같이 사용 가능.

출처 : https://ryublock.tistory.com/42

profile
Let's do it developer

0개의 댓글