React DND typescript support React DND typescript support typescript typescript

React DND typescript support


I've got it working with the DT types package on 2.1. It doesn't compile with strictNullChecks and I haven't been able to track down the reason why. (When you decorate your components with @DragSource and @DropTarget, you somehow change the return type of the render function from Element to Element | null, but I can't see how.)

The other niggle is that all of the props that are inserted by the collecting function are undefined when you first instantiate your components in a render method, so your options are to pass a bunch of {undefined as any} or else declare your collector-injected props as optionals and typeguard them out every where you look at them. Overall the type declaration file is not bad and I found the typing to be more helpful than harmful when getting to know the library.

import {     ConnectDragSource,    DragDropContext,     DragSource,     DragSourceSpec,     DragSourceCollector,     DragSourceConnector,     DragSourceMonitor,     DragElementWrapper,    ConnectDropTarget,    DropTarget,    DropTargetConnector,    DropTargetMonitor,    ClientOffset,    DropTargetSpec } from 'react-dnd';let HTML5Backend = require('react-dnd-html5-backend');import { AdjacencyMatrixGraph } from "Geometry/Graph";import * as React from "react";import * as Sauce from "Sauce";import * as ReactDOM from "react-dom";import * as $ from "jquery";import { Position2 } from "Geometry";import * as Rx from "rxjs";import * as Util from "Util";require("./GraphBuilder.scss");interface NodeProps {  label?: string;  position: ClientOffset;}/* New node from the node well */export interface NodeSourceProps {   isDragging : boolean;   connectDragSource: ConnectDragSource;}export interface NodeSourceState {}// Spec: drag events to handle.let nodeSourceSpec: DragSourceSpec<NodeSourceProps> = {    beginDrag: (props: NodeSourceProps) => ({}),};// Collect: Put drag state into propslet nodeSourceCollector = (connect: DragSourceConnector, monitor: DragSourceMonitor) => {    return {      connectDragSource: connect.dragSource(),      isDragging: monitor.isDragging()  }};@DragSource("new-node", nodeSourceSpec, nodeSourceCollector)export class NodeSource extends React.Component<NodeSourceProps, NodeSourceState> {  constructor(props: NodeSourceProps) {    super(props);  }  render() {    const { connectDragSource, isDragging } = this.props;    return connectDragSource(<span className="node-source">{'\u2683'}</span>);  }}/* main graph area */interface GraphCanvasProps {    connectDropTarget: ConnectDropTarget,    isOver: boolean,    graph: AdjacencyMatrixGraph<NodeProps>;}interface GraphCanvasState {}const canvasDropTargetSpecification: DropTargetSpec<GraphCanvasProps> = {  drop(props: GraphCanvasProps, monitor: DropTargetMonitor, component: React.Component<GraphCanvasProps, any>) {    // console.log("Handling drop", print_monitor(monitor));    let pos = monitor.getSourceClientOffset();    if (monitor.getItemType() === "main-node-move") {      let node = (monitor.getItem() as any);      graph.setData(node.id, { position: pos });    }    else if (monitor.getItemType() === "new-node") {      graph.addNode("node-" + graph.order(), { position: pos });    }  },};function canvasDropTargetCollectingFunction(connect: DropTargetConnector, monitor: DropTargetMonitor) {  let rv = {    connectDropTarget: connect.dropTarget(),    isOver: monitor.isOver(),  };  return rv;}/* ... here's  a DropTarget ... */@DropTarget(["main-node-move", "new-node"], canvasDropTargetSpecification, canvasDropTargetCollectingFunction)export class GraphCanvas extends React.Component<GraphCanvasProps, GraphCanvasState> {  constructor(props: GraphCanvasProps) {    super(props);  }  render(): JSX.Element | null {    const { connectDropTarget, graph } = this.props;    let nodes = graph.nodes();    let nodeEls = Object.keys(nodes).map(k => {      let node = nodes[k];      return <CanvasNode       key={k}       id={k}       node={node}       graph={graph}       connectNodeDrop={null as any}       connectMoveNodeDragger={(null)}/>    });    return connectDropTarget(<div className="graph-canvas">      {nodeEls}    </div>);  }}/* ... Here's a the DragContext decorator ... */@DragDropContext(HTML5Backend)class Markov extends React.Component<MarkovProps, MarkovState>  {