All Articles

React + Mobx 구현하기 (1)

MobX

  • immer가 기본적으로 적용되있다고 보면 된다.

  • redux보다 더 간결함.

  • state가 있으면 action은 state를 변경한다. 끝!

ex)

observable(state) -----> observer { naem: ‘zero’,
age: 26,
married: false }

↑↓

[action] state.name = ‘nero’

—> state가 있고, state를 observable이 감싸고 있고, state를 편하게 객체 값을 바꾸듯이 바꿀 때마다, observable들이 observer들한테 알려준다.

const { observable, autorun, reaction, action, runInAction } = require('mobx');

// redux의 initialState 부분
const state = observable({
  compA: 'a',
  compB: 12,
  compC: null,
});

// 리덕스는 리듀서가 필수이기 때문에, 리듀서를 연결하기 위해 사용
// Mobx는 state를 observable로 감싸면 끝!
// const store = createStore(reducer, initialState);

// observable state가 바뀔 때마다 autorun 안의 콜백함수를 실행 (state 변경 감지기)
autorun(() => {
  console.log('changed');
});

// (state 변경 감지기) 첫 번째 인수인 함수의 리턴하는 값이 변경되었을 때만 실행 (compB가 변경될때만 실행)
reaction(() => {
  return state.compB;
}, () => {
  console.log('reaction', state.compB);
});


// redux의 액션 생성, dispatch 다 필요 없고, MobX는 객체처럼 바로 변경 가능
state.compA = 'b';
state.compB = 'c';
state.compC = 'c';
// Mobx는 3개의 액션을 일련의 하나의 액션으로 취급해서 'changed'가 한번만 출력됨

runInAction(() => {
  state.compA = 'b';
  state.compB = 'c';
  state.compC = 'c';
}); // 이게 하나의 액션이야!! 안써도 무방!

action과 runInAction은 유사한 관계가 있음.
  • action은 함수처럼 따로 생성해놓고, 필요할 때 호출
  • runInAction은 바로 실행
// 필요할 때 실행
const change = action(() => {
  state.compA = 'c';
  state.compB = 25;
  state.compC = 'c';
});

// 바로 실행
runInAction(() => {
  state.compA = 'c';
  state.compB = 25;
  state.compC = 'c';
});

observable로 묶는다면 state 그룹 선언 가능

cf) redux는 initialState 안에 하나의 큰 객체({}) 안에 state들이 존재

const userState = observable({
  isLoggingIn: true,
  data: null,
});

const postState = observable([]);

postState.push({ id: 1, content: '안녕하세요.' });
userState.data = {
  id: 1,
  nickname: 'zerocho',
};

로그인을 하면서 동시에 글을 작성하고 싶은 경우
runInAction(() => {
  postState.push({ id: 1, content: '안녕하세요.' });
  userState.data = {
    id: 1,
    nickname: 'zerocho',
  };
});

redux 같은 경우엔, user와 post가 분리하여 생성하기 때문에 위의 작업을 동시에 진행하기 위해서는 액션을 두 개 생성하여 동시에 실행시켜야 한다.

reducer 사이를 넘나들며 데이터(state)를 변경하기 매우 힘들다.


class로 Mobx 사용하기
class UserStore {
  state = observable({
    name: 'zerocho',
    age: 26,
  });

  @action
  changeName(value) {
    this.state.name = value;
  }
}

const userStore = new UserStore(); // 싱글턴

class를 사용하는 이유는 ????? —> 새로운 인스턴스(new)를 여러개 찍어내기 위해 사용

UserStore를 2번 인스턴스를 생성해서 만들 필요 없다고 생각. 클라이언트(프론트)에선 한 명의 사용자가 로그아웃 하기 전까진, 다른 사용자가 로그인할 수 없기 때문에.

아래는 위의 class로 선언한 것을 함수형으로 구현했을 때,

const userState = observable({
  name: 'zerocho',
  age: 26,
  changeName(value) {
    this.name = value;
  }
});


참고

  • 인프런 강의 (zerocho)