LoginSignup
1
0

More than 5 years have passed since last update.

react-dnd の tutorial を typescript mobx で写経した

Posted at

目的

typescript と react-dnd と mobx を使う場合に、デコレータの組み合わせでどうなるか、を確認したかった。

経緯

mobx使ってる個人的なプロジェクトで、drag and drop したいかも。と思って、
react drag and drop でググってトップに出てきた react-dnd さんを確認してた

ドキュメント読んでて、デコレータ使ってた

mobx との相性問題とか出ないのかな。と気になったので

チュートリアル を写経ついでにmobx化

成果物

Tips

storeを参照したいreact-dndのデコレータに@injectつける

Chessboard.tsx
@inject("gameStore")
@DropTarget(
  ItemTypes.KNIGHT,
  BoardSquare.squareTarget,
  BoardSquare.dropCollector
)
class BoardSquare extends React.Component<

DropTargetに渡した squareTarget さんは、
BoardSquare を使う側で渡したpropsを使ってゴニョゴニョする。

Chessboard.tsx
@DropTarget(
  ItemTypes.KNIGHT,
  BoardSquare.squareTarget,
  BoardSquare.dropCollector
)
@inject("gameStore")
class BoardSquare extends React.Component<

この順だと、 squareTarget から gameStore を参照できない。

ちなみに squareTarget.drop だと第3引数に component が渡されてくる。
squareTarget.propsで頑張る方向もあるのかな。と思ってたのだけど、
canDrop を使い始めたところで第3引数が無くて死んだ。
DropTargetから見ると子となる、BoardSquareの状態を読むような形は作りとして微妙な感じがするので、
inject -> DropTarget で propsを引き継ぐのがきっと良いのだと納得することにした。

collector の型がpropsに渡されてくるので使いやすいように頑張る

react-dnd と mobx の組み合わせというより、react-dnd と typescript 的なTips

Chessboard.tsx
type OptionalPropertyNames<T> = { [K in keyof T]?: T[K] };
type OptionalReturnType<
  T extends (...args: any[]) => any
> = OptionalPropertyNames<ReturnType<T>>;

ReturnTypeだけだと以下のようなOptionalじゃない型が取れるので、

interface {
  connectDragSource: Function;
  connectDragPreview: Function;
  isDragging: Function;
}

使うところで上記のprops指定しないとエラーになってしまう。

それを抑制しつつ、中ではpropsとして使えるように、OptionalReturnType というものを拵えた。
(そもそも 2.8から入った ReturnType を知らなくて、これ便利と、大興奮。)
(別件で React.Component<P, S>P を使ってゴニョゴニョしてどこかで幸せになれないかな。と思ってる。)

細かい変更

source/collector を componentのstaticメソッドにしてみた

Chessboard.tsx
@DragSource(ItemTypes.KNIGHT, Knight.dragSource(), Knight.dragCollector)
class Knight extends React.Component<

操作なり状態について処理するときはstoreに任せるようにした

Chessboard.tsx
  static squareTarget = {
    canDrop(props, src) {
      return props.gameStore.canMoveKnight(props.x, props.y);
    },
    drop(props, src, component) {
      props.gameStore.moveKnight(props.x, props.y);
    }
  };

参考サイト

Appendix

  • codesandbox https://codesandbox.io/
    • 初めて使ったけど、結構使えるなー。と思った
    • 微妙に使いづらい所はあった
      • auto-reload でプレビューがエラーになる
      • 間違ってforkしちゃった
      • project 読み込み直したらエラーいっぱいになった
1
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0