[React] Mobx-state-tree 학습하기 #11 : 더 많은 mobx-state-tree Types 배우기: map, literal, union, enumeration

이전글 "[React] Mobx-state-tree 학습하기 #10 : Model Definitions Change되면 Hot Module Reloading를 사용하여 Model Tree State 복원하기"에서 이어지는 ...

3 months ago, comments: 1, votes: 48, reward: $0.81

이전글 "[React] Mobx-state-tree 학습하기 #10 : Model Definitions Change되면 Hot Module Reloading를 사용하여 Model Tree State 복원하기"에서 이어지는 내용입니다. 참고로 이 포스팅은 제가 학습한 내용을 노트에 정리하듯이 기록하여 올리는 글이기 때문에 보팅 안해주셔서 됩니다. 많은 분들이 코딩에 흥미를 느꼈으면 좋겠습니다. ㅋ





More mobx-state-tree Types: map, literal, union, and enumeration


11번째 레슨입니다. 이번 레슨에서는 그룹 및 사용자의 개념을 소개합니다. 그룹 내에 여러 사용자를 관리할 수 있습니다. 그리고 각 사용자들은 각각의 위시 리스트를 가질 수 ​​있습니다. 또한 union 타입과 타입 discrimination의 강력한 기능을 간단히 살펴볼 것입니다.


우리는 이번 레슨에서 다음을 배우게 됩니다.

  • key로 데이터를 저장하기 위해 type map 사용하기
  • single value types를 생성하기 위해 literals 사용하기
  • type discrimination 하기 위해 literals 과 unions을 Combining 하기
  • quick coding experiments를 위해 Quokka를 scratchpad로 사용하기
  • enumerations 사용하기
  • Enumerations는 literals의 union에 대한 just sugar 이다. 🤔




이제 사용자 그룹을 만들고 각 사용자가 각자의 위시 리스트를 가지도록 모델을 개선해 봅시다.


User 모델 만들기

groups.js 파일을 새로 생성합니다. 그리고 User 모델을 정의 합니다. User 모델은 idname, 그리고 gender 속성을 가집니다.

src/models/Group.js

import { types } from 'mobx-state-tree';

const User = types.model({
    id: types.string,
    name: types.string,
    gender: types.union(types.literal('m'), types.literal('f'))
});

타입을 선택할 수 있는 유형을 일반적으로 union이라 합니다. 두 가지 타입을 결합하여 gender을 표현하게 됩니다. 여기서 gender 값은 반드시 m 또는 f 여야합니다.




Quokka 사용하여 빠르게 테스트해보기

VSCode의 익스텐션 프로그램 Quokka를 사용하면 자바스크립트 또는 타입스크립트를 스크래치 패드에서 빠르게 만들고 실행할 수 있습니다.

VSCode에 Quokka 익스텐션을 설치합니다.


그다음 단축키 Cmd + Shift + P를 눌러 Quokka에서 New File를 생성합니다.

위에서 작성한 코드를 Quokka에 복사&붙여넣기 합니다. 그리고 User 모델 인스턴스를 생성하고 genger 속성에 m 또는 f 외에 엉뚱한 값을 넣어보세요. 그럼 다음과 같이 잘못된 타입이라는 에러가 발생합니다.

하지만 gengerm 값을 입력하면 다음과 같이 에러가 발생하지 않습니다.

이제 Man과 Woman 모델을 각각 정의하고, 이 두 모델을 다시 union하여 Human을 정의해봅시다. 그리고 나서 Human 인스턴스를 생성할때 genderm을 입력하여 somebody를 생성합니다. 우리는 somebody가 man인지 아닌지 간단히 확인할 수 있습니다.

import { types } from 'mobx-state-tree';

const Man = types.model({
    id: types.string,
    name: types.string,
    gender: types.literal('m')
});

const Woman = types.model({
    id: types.string,
    name: types.string,
    gender: types.literal('f')
});

const Human = types.union(Man, Woman);

const someone = Human.create({
    id: "123",
    name: "michel",
    gender: "m"
})

console.log(Man.is(someone))
console.log(Woman.is(someone))

Man.is(someone)true, 그리고 Woman.is(someone)flase가 출력됩니다.




enumeration 사용하기

literal을 union하는 방식인 types.union(types.literal('m'), types.literal('f')) 이 가장 일반적인 패턴입니다. 하지만 더 간단한 표기법이 있습니다. 이를 enumeration이라고 합니다. User 모델의 gender Type을 enumeration를 사용하여 다시 표현하면 types.enumeration("gender", ["m", "f"])가 됩니다.

src/models/Group.js

import { types } from 'mobx-state-tree';

export const User = types.model({
    id: types.string,
    name: types.string,
    gender: types.enumeration("gender", ["m", "f"])
});


그다음 User 모델에 wishList 속성을 정의합니다. wishListoptional 이며, 디폴트값은 비어있는 Object {}입니다.

src/models/Group.js

import { types } from 'mobx-state-tree';

import { WishList } from "./WishList"; // add here

export const User = types.model({
    id: types.string,
    name: types.string,
    gender: types.enumeration("gender", ["m", "f"])

    wishList: types.optional(WishList, {}) // add here
});




Group 모델 만들기

이제 Group을 정의 합니다. Group은 User 그룹이라고 할 수 있습니다. 여기에서는 Map를 사용하였습니다. 하지만 우리는 Array를 사용할 수도 있습니다. Group.js 파일 맨 아래에 다음 코드를 입력합니다.

src/models/Group.js

// ...

export const Group = types.model({
  users: types.map(User)
});





다음은 지금까지 작성된 Group.js 파일의 전체 내용입니다.

src/models/Group.js

import { types } from "mobx-state-tree";
import { WishList } from "./WishList";

export const User = types.model({
  id: types.string,
  name: types.string,
  gender: types.enumeration("gender", ["m", "f"]),
  wishList: types.optional(WishList, {})
});

export const Group = types.model({
  users: types.map(User)
});




UI 수정하기

모델을 재구성했으니 이제 UI를 수정해야합니다. index.js 파일을 편집합니다.

Group 모델을 import 합니다. 그리고 간단한 작업을 위해 initialState에는 심슨 가족 데이터 셋트를 미리 준비했습니다.

src/index.js

// ...

import { Group } from "./models/Group";

let initialState = {
  usres: {
    "a342": {
      id: "a342",
      name: "Homer",
      gender: "m"
    },
    "5fc2": {
      id: "5fc2",
      name: "Marge",
      gender: "f"
    },
    "663b": {
      id: "663b",
      name: "Bart",
      gender: "m"
    },
    "65aa": {
      id: "65aa",
      name: "Maggie",
      gender: "f"
    },
    "ba32": {
      id: "ba32",
      name: "Lisa",
      gender: "f"
    }
  }
}

// ...

let group = Group.create(initialState);

function renderApp() {
  ReactDOM.render(<App group={group} />, document.getElementById("root"));
}

// ...


그다음 선택 박스에서 사용자를 선택하면 위시 리스트 목록, 편집 화면이 보이도록 고쳐보겠습니다. App.js 파일을 수정합니다.

참고로 동영상 강의에서는 group.users.values().map 를 사용하고 있습니다. 하지만 Mobx 2에서 사용방법이 변경되었습니다. Array.from(group.users.values()).map 또는 values(group.users).map 를 사용하세요.

src/components/App.js

import React from "react";
import { values } from 'mobx';
import "./App.css";

import WishListView from "./WishListView";

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      selectUser: null
    };
  }

  render() {
    const { group } = this.props;
    const selectedUser = group.users.get(this.state.selectUser)
    return (
      <div>
        <h1 className="App-title">WishList</h1>

        <select onChange={this.onSelectUser}>
          <option>- Select user -</option>
          {{values(group.users).map(user => (
            <option key={user.id} value={user.id}>
              {user.name}
            </option>
          ))}
        </select>

        {
          selectedUser && <WishListView wishList={selectedUser.wishList} />
        }
      </div>
    );
  }

  onSelectUser = event => {
    this.setState({
      selectUser: event.target.value
    })
  };
}

export default App;

실행화면


오늘 수업 끝.




댓글, 팔로우, 좋아요 해 주시는 모든 분께 감사합니다.

항상 행복한 하루 보내시길 바랍니다.


vote, reblog, follow @anpigon