简体   繁体   English

为什么 `dataTransfer` 方法为我的对象返回 null?

[英]Why is the `dataTransfer` method returning null for my objects?

I'm building a drag and drop application using React and I'm following this tutorial: https://jsfiddle.net/xv5mu40h/8/ .我正在使用 React 构建拖放应用程序,并且正在学习本教程: https://jsfiddle.net/xv5mu40h/8/

However, when I try it on my end, I get this error message: TypeError: Cannot read property 'cloneNode' of null , talking specifically about this line of code: const nodeCopy = document.getElementById(data).cloneNode(true);但是,当我最终尝试时,我收到以下错误消息: TypeError: Cannot read property 'cloneNode' of null ,专门讨论这行代码: const nodeCopy = document.getElementById(data).cloneNode(true); . .

I've console logged what data is before this line of code and it appears that data is null when I try to drag and drop any of the objects (which I call rewards in this case).我已经在控制台记录了这行代码之前的data ,当我尝试拖放任何对象(在这种情况下我称之为奖励)时, data似乎是 null。 Any help is appreciated!任何帮助表示赞赏!

NOTE: I've taken out as much of the irrelevant code as possible;注意:我已经尽可能多地删除了不相关的代码; for more focus points, I believe that the problem lies in the dragging/dropping function (not in any of the lifecycle methods or the unique identifier method).对于更多焦点,我认为问题在于拖放 function (不在任何生命周期方法或唯一标识符方法中)。

class Home extends Component {
  // Constructor for home
  constructor(props) {
    super(props);
    this.state = {
      rewards: [],
      cat1Counter: 1,
      cat2Counter: 1,
      cat3Counter: 1,
      cat4Counter: 1,
      cat5Counter: 1
    };
  }

  // Fetch rewards once component mounts
  componentDidMount() {
    this.props.fetchRewards();
  }

  // Update local state once all rewards are fetched
  componentDidUpdate(prevProps) {
    if (this.props.rewards !== prevProps.rewards) this.setState({rewards: this.props.rewards});
  }

  // Creates a unique ID for a reward copy
  getUniqueId(prefix) {
    let id = '';
    if (prefix === 'reward-1') {
      id = `${prefix} copy-${this.state.cat1Counter++}`
    } else if (prefix === 'reward-2') {
      id = `${prefix} copy-${this.state.cat2Counter++}`
    } else if (prefix === 'reward-3') {
      id = `${prefix} copy-${this.state.cat3Counter++}`
    } else if (prefix === 'reward-4') {
      id = `${prefix} copy-${this.state.cat4Counter++}`
    } else if (prefix === 'reward-5') {
      id = `${prefix} copy-${this.state.cat5Counter++}`
    }

    return id;
  }

  // Allow for elements to be dropped in other elements
  allowDrop(e) {
    e.preventDefault();
  }

  // Removes a node
  removeNode(node) {
    node.parentNode.removeChild(node);
  }

  // Drags a reward
  drag(e) {
    e.dataTransfer.setData('text', e.target.id);
  }

  // Drops the reward
  drop(e) {
    e.preventDefault();
    const data = e.dataTransfer.getData('text');
    const isLeft = 'reward-1' === data || 'reward-2' === data;

    const nodeCopy = document.getElementById(data).cloneNode(true);
    nodeCopy.id = `${this.getUniqueId(data)}`;

    if (isLeft) {
      e.target.appendChild(nodeCopy);
    } else {
      if (e.target.id !== 'P') {
        this.removeNode(document.getElementById(data));
        e.target.appendChild(nodeCopy);
      }
    }

    e.stopPropagation();
    return false;
  }

  render () {
    return (
      <div className="home-container">
        <div className="rewards-container">
          <h2>Rewards</h2>

          <ul>
            {this.state.rewards.map(reward => <li key={reward._id} draggable onDragStart={e => this.drag(e)}>{reward.name}</li>)}
          </ul>
        </div>

        <div className="categories-container">
          <h2>Categories</h2>

          <div className="list-wrapper">
            <ul id="category-1" onDrop={e => this.drop(e)} onDragOver={e => this.allowDrop(e)}><p>C1</p></ul>
            <ul id="category-2" onDrop={e => this.drop(e)} onDragOver={e => this.allowDrop(e)}><p>C2</p></ul>
            <ul id="category-3" onDrop={e => this.drop(e)} onDragOver={e => this.allowDrop(e)}><p>C3</p></ul>
            <ul id="category-4" onDrop={e => this.drop(e)} onDragOver={e => this.allowDrop(e)}><p>C4</p></ul>
            <ul id="category-5" onDrop={e => this.drop(e)} onDragOver={e => this.allowDrop(e)}><p>C5</p></ul>
          </div>
        </div>
      </div>
    );
  }
};

UPDATE更新

Per the answer below, I've changed onDrag to onDragStart and now it works when I drag objects from the rewards list into the categories;根据下面的答案,我已将onDrag更改为onDragStart ,现在当我将奖励列表中的对象拖入类别时它可以工作; however, the bug still pops up when I try dragging cloned objects in between categories.但是,当我尝试在类别之间拖动克隆对象时,仍然会弹出该错误。

You have to set the data onDragStart.您必须在DragStart 上设置数据。 The onDrag would be called every time you drag and might be not the right place to set.每次拖动时都会调用 onDrag 并且可能不是正确的设置位置。 You could change onDrag to onDragStart您可以将 onDrag 更改为 onDragStart

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM