目的
typescript と react-dnd と mobx を使う場合に、デコレータの組み合わせでどうなるか、を確認したかった。
経緯
mobx使ってる個人的なプロジェクトで、drag and drop したいかも。と思って、
react drag and drop
でググってトップに出てきた react-dnd さんを確認してた
ドキュメント読んでて、デコレータ使ってた
の チュートリアル を写経ついでにmobx化
成果物
Tips
storeを参照したいreact-dndのデコレータに@injectつける
@inject("gameStore")
@DropTarget(
ItemTypes.KNIGHT,
BoardSquare.squareTarget,
BoardSquare.dropCollector
)
class BoardSquare extends React.Component<
DropTargetに渡した squareTarget さんは、
BoardSquare を使う側で渡したpropsを使ってゴニョゴニョする。
@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
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メソッドにしてみた
@DragSource(ItemTypes.KNIGHT, Knight.dragSource(), Knight.dragCollector)
class Knight extends React.Component<
操作なり状態について処理するときはstoreに任せるようにした
static squareTarget = {
canDrop(props, src) {
return props.gameStore.canMoveKnight(props.x, props.y);
},
drop(props, src, component) {
props.gameStore.moveKnight(props.x, props.y);
}
};
参考サイト
- react-dnd
- Qiita
-
react-コンポーネント > drag-and-drop
https://qiita.com/sugasaki/items/dcf893e0189042468f88- 他にもこんなものがあるのかーと眺めている最中
- react-dnd は touch に対応してないのか。なるほど。etc
-
Appendix
- codesandbox https://codesandbox.io/
- 初めて使ったけど、結構使えるなー。と思った
- 微妙に使いづらい所はあった
- auto-reload でプレビューがエラーになる
- 間違ってforkしちゃった
- project 読み込み直したらエラーいっぱいになった