React-dnd: findDOMNode()を使用した例

作成日 2016年12月06日  ·  11コメント  ·  ソース: react-dnd/react-dnd

findDOMNode()の使用は推奨されなくなりました。 実際、それを使用する場合、Reactは使用しないように警告します。 いくつかの例では、refを使用して置き換えることができないと思われる場所でfindDOMNodeを使用しています。 findDOMNodeを使用する必要がなくなった場合は、他のものを使用するようにこれらを更新する必要があります。

この具体的な例の1つは、 https ://github.com/gaearon/react-dnd/blob/master/examples/04%20Sortable/Simple/Card.js#L34です。

const cardTarget = {
  hover(props, monitor, component) {
    const dragIndex = monitor.getItem().index;
    const hoverIndex = props.index;

    // Don't replace items with themselves
    if (dragIndex === hoverIndex) {
      return;
    }

    // Determine rectangle on screen
    const hoverBoundingRect = findDOMNode(component).getBoundingClientRect();

    // Get vertical middle
    const hoverMiddleY = (hoverBoundingRect.bottom - hoverBoundingRect.top) / 2;

    // Determine mouse position
    const clientOffset = monitor.getClientOffset();

    // Get pixels to the top
    const hoverClientY = clientOffset.y - hoverBoundingRect.top;

    // Only perform the move when the mouse has crossed half of the items height
    // When dragging downwards, only move when the cursor is below 50%
    // When dragging upwards, only move when the cursor is above 50%

    // Dragging downwards
    if (dragIndex < hoverIndex && hoverClientY < hoverMiddleY) {
      return;
    }

    // Dragging upwards
    if (dragIndex > hoverIndex && hoverClientY > hoverMiddleY) {
      return;
    }

    // Time to actually perform the action
    props.moveCard(dragIndex, hoverIndex);

    // Note: we're mutating the monitor item here!
    // Generally it's better to avoid mutations,
    // but it's good here for the sake of performance
    // to avoid expensive index searches.
    monitor.getItem().index = hoverIndex;
  }
};

その他の例: https ://github.com/gaearon/react-dnd/search?l = JavaScript&q = finddomnode&utf8 =%E2%9C%93

これを解決するための推奨される方法は何ですか?

wontfix

最も参考になるコメント

動作しています! トリックは最初にconnectDropTargetを呼び出すことでした。 connectDragSourcedecoratedComponentInstance $を設定するとは思いません(何らかの理由でref変数がcomponentに設定されていないため、 component.decoratedComponentInstanceでのみ使用できます)。

作業バージョンは次のようになります。

class NavigationItem extends React.Component
  render() {
    return this.props.connectDragSource(this.props.connectDropTarget(
      <section
        ref={node => (this.node = node)}
      >
       {this.props.name}
      </section>
    ));
  }
}
const navItemDropSource = {
  hover: (props, monitor, component) => {
    console.log(component.decoratedComponentInstance.node.getBoundingClientRect());
  }
}

助けてくれてありがとう@beniutek

全てのコメント11件

推奨される方法は、参照を使用することです。https ://facebook.github.io/react/docs/refs-and-the-dom.htmlを参照してください。

その後、 component.passedRefName.getBoundingClientRect()を呼び出すことにより、渡された参照にアクセスできます。

私たちがそれを私たちの側で修正した方法は次のとおりです:

ドラッグ可能なもの:

<li className="draggable-card" ref={(elm) => {this.card = elm;}}>

そして、 DropTarget hoverメソッドの内部。

hover (props, monitor, component) {
     // code
    const {decoratedComponentInstance} = component;
    const hoverBoundingRect = decoratedComponentInstance.card.getBoundingClientRect();
    // code
}

これについてもっと良い方法があるかどうかはわかりません。おそらく@gaearonがこれに光を当てることができます。 それは大歓迎です。

これは、Facebookのドキュメントから推奨される方法です。 同じようにやっています

時間があれば、後で見ていきます。 それまでの間、PRをお気軽にカットしてください

refアプローチを採用していますが、 component.decoratedComponentInstancenullです。

参考までに、コンポーネントはドラッグとドロップの両方が可能です。

export default flow(
  DragSource('NavItem', navItemDragSource, dragCollect),
  DropTarget('NavItem', navItemDropSource, dropCollect)
)(NavigationItem);

NavigationItemコンポーネントは、 hoverで使用する予定の参照を設定します。

class NavigationItem extends React.Component
  render() {
    return this.props.connectDropTarget(this.props.connectDragSource(
      <section
        ref={element => (this.navItemElement = element)}
     </section>
  }
}

そしてhover

const navItemDropSource = {
  hover: (props, monitor, component) => {
    console.log(component.decoratedComponentInstance); // prints null
  }
}

ここで何が欠けているのか分かりますか?

@ndelage

私たちのアプリでは、おおよそ次のようになります。

..some code

const itemTarget = {
  hover(props, monitor, component) {
    if (monitor.isOver()) {
      ...some code

       const bounds = component.node.getBoundingClientRect()

       ...some code
       return result;
    }
  }
}

..some code

@DragSource(ITEM_TYPE, itemSource, collectSource)
@DropTarget(ITEM_TYPE, itemTarget, collectDrop)

class DraggableItem extends Component {
  render() {
    const { connectDragSource, connectDropTarget } = this.props;

    return connectDragSource(
      connectDropTarget(
        <div
          className="draggable-item"
          ref={ node => (this.node = node) }
        >
          <Item { ...this.props } />
        </div>
      )
    );
  }
}

export default DraggableItem

あなたの例では、要素paramをthis.naItemElementに割り当てていることがわかりますが、 hoverメソッドでは、 naItemElementをまったく参照していません。 あなたはそれをそのようなものと呼ぶべきです:

const navItemDropSource = {
  hover: (props, monitor, component) => {
    console.log(component.navItemElement); // you should get the DOM node reference now
  }
}

動作しています! トリックは最初にconnectDropTargetを呼び出すことでした。 connectDragSourcedecoratedComponentInstance $を設定するとは思いません(何らかの理由でref変数がcomponentに設定されていないため、 component.decoratedComponentInstanceでのみ使用できます)。

作業バージョンは次のようになります。

class NavigationItem extends React.Component
  render() {
    return this.props.connectDragSource(this.props.connectDropTarget(
      <section
        ref={node => (this.node = node)}
      >
       {this.props.name}
      </section>
    ));
  }
}
const navItemDropSource = {
  hover: (props, monitor, component) => {
    console.log(component.decoratedComponentInstance.node.getBoundingClientRect());
  }
}

助けてくれてありがとう@beniutek

この機能が廃止されることを心配しているのは私だけではありません。 私は現在、 https://github.com/mozmorris/react-webcamにあるサードパーティの「Webcam」コンポーネントを使用しています。 このコンポーネントはfindDOMNodeを使用しており、refを使用して機能を置き換える方法がわかりません。 注:ここでrefが使用されていることはわかりますが、src / react-webcam.jsの(非常に短い)ソースコードを見ると、findDOMNodeも使用されています。

このコンポーネントの簡単な使用例を次に示します。

class WebcamCapture extends React.Component {
  setRef = (webcam) => {
    this.webcam = webcam;
  }

  capture = () => {
    const imageSrc = this.webcam.getScreenshot();
  };

  render() {
    return (
      <div>
        <Webcam
          audio={false}
          height={350}
          ref={this.setRef}
          screenshotFormat="image/jpeg"
          width={350}
        />
        <button onClick={this.capture}>Capture photo</button>
      </div>
    );
  }
}

refsを使用するようにこれを変更したい場合、サンプルコードでは、このサードパーティライブラリのユーザーがビデオdom要素とgetusermediaAPIを使用しているWebカメラコンポーネントのdom構造を理解する必要があると思います。 サードパーティのコンポーネントユーザーにコンポーネントのDOM構造を理解するように要求することは、控えめに言っても理想的ではありません。 refを使用してこれを行うためのより簡単な方法が見つからない場合はお知らせください。

この問題に苦労し、 @ ndelage@beniutekのソリューションを使おうとする人のために、 component.decoratedComponentInstancecomponent.getDecoratedComponentInstance()に置き換えられました(ここに記載されています)。

必要なものは次のとおりです。

class NavigationItem extends React.Component
  constructor(props){
    super(props);
    this.node = React.createRef();
  }
  render() {
    const { connectDragSource, connectDropTarget } = this.props;
    return connectDragSource(connectDropTarget(
      <section ref={this.node}>
       {this.props.name}
      </section>
    ));
  }
}
const navItemDropSource = {
  hover: (props, monitor, component) => {
    console.log(component.getDecoratedComponentInstance().node.getBoundingClientRect());
  }
}

誰かがすぐに例を更新できるようになることを願っています。

画像上にいくつかのピンを追加し、ドロップコンポーネントのビューポート位置を取得するために、 @ QuentinRoyが提案したように参照nodeを追加しましたが、 getDecoratedComponentInstance()は機能しませんでした(関数)。

ドロップターゲット仕様のdropメソッドのcomponentパラメーターでnode参照を直接取得できることを確認しました。

drop: (props, monitor, component) => {
   console.log(component.node.current.getBoundingClientRect())
}

この問題は、最近のアクティビティがないため、自動的に古いものとしてマークされています。 それ以上のアクティビティが発生しない場合は閉じられます。 貢献していただきありがとうございます。

このページは役に立ちましたか?
0 / 5 - 0 評価