道具为什么不更新?

时间:2019-02-26 15:42:21

标签: reactjs draggable

我正在尝试将可拖动属性添加到已渲染的组件中,但是,我不知道确切将它们添加到何处。因此,它们至少会渲染出来,但是当删除该项目时,数组不会在OnDragEnd上更新。组件:

const Item = props => { 
const finishedButton = <button onClick={props.handleComplete} className="finishedButton">✔</button>

 return (     
    <li className="background" 
        draggable
        onDragStart={props.dragStart}    
        onDragEnd={props.dragEnd}
        >      
      {finishedButton}{props.item}
   </li>

以及在应用程序的渲染中

  <ul  onDragOver={e => this.dragOver(e)}>
     {this.state.items.map((item, i)=> (
      <Item
       data-id={i}
       key={i}
       dragStart={e => this.dragStart(e)}
       dragEnd={e => this.dragEnd(e)}
       item={item.text}
       />
     ))}     
    </ul> 

Codepen:https://codepen.io/Matt-dc/pen/zbYKNv

2 个答案:

答案 0 :(得分:0)

在您的dragEnd函数中this.draggedElem未定义。因此prevIndexnewIndex也未定义,这导致data.splice返回旧状态。

答案 1 :(得分:0)

我不确定您的逻辑,但似乎可行

let placeholder = document.createElement("li");
placeholder.className = "placeholder";

    const Item = props => { 
        const finishedButton = <button onClick={props.handleComplete} className="finishedButton">✔</button>

         return (     
            <li className="background" 
                draggable          
                onDragStart={props.dragStart}    
                onDragEnd={props.dragEnd}
                onDragOver={props.dragOver}
                >      
              {finishedButton}{props.item}
             >

           </li>
      );
    }


    class App extends React.Component { 

      constructor(props) {
        super(props);

        this.state = {
          items: [
                {id: 1, text: "clean car", complete: false},
                {id: 2, text: "wash dog", complete: false},
                {id: 3, text: "water plants", complete: false},
                {id: 4, text: "prune shrubs", complete: false},
                {id: 5, text: "tidy house", complete: false}
          ],
          input: ""
        }
        this.dragStart = this.dragStart.bind(this);
        this.dragOver = this.dragOver.bind(this);
        this.dragEnd = this.dragEnd.bind(this);
        this.handleChange = this.handleChange.bind(this);
        this.handleSubmit = this.handleSubmit.bind(this);

      }

      handleChange = e => {
        this.setState({
          input: e.target.value
        });
      }

      handleSubmit = () => {
        let newItem = {};
          newItem.id = uuid.v4();
          newItem.text = this.state.input;
          newItem.complete = false; 
        let newItems = this.state.items.concat(newItem);

        this.setState({
          items: newItems,

        });  
        this.setState({input: ''})
      }

      handleComplete = e => {


      }

      dragStart = e => {
        this.draggedElem = e.target;
        e.dataTransfer.setData('text/html', this.draggedElem);    
      }

      dragOver = e => {
        e.preventDefault();
        //this.draggedElem.style.display = "none";
        if(e.target.className === 'placeholder') return;
        this.newIndex = e.target
      }

        dragOverItem = (id,e) => {
        this.to = id;
      }

      dragEnd = (from,e) => {

        let data = this.state.items;
        let prevIndex = from; 
        let newIndex = this.to;
        console.log(`from ${prevIndex} to ${newIndex}`)
        //if(prevIndex < newIndex) newIndex --;
        data.splice(newIndex, 0, data.splice(prevIndex, 1)[0]);

        this.setState({ items: data });
      }

      render() {

        return(

          <div>

            <input onChange={this.handleChange} value={this.state.input} />
            <button onClick={this.handleSubmit}>Add item</button>

            <ul onDragOver={this.dragOver}>
             {this.state.items.map((item, i)=> (
              <Item
               data-id={i}
               key={i}
                dragOver={this.dragOverItem.bind(this,i)}
               dragStart={e => this.dragStart(e)}
               dragEnd={this.dragEnd.bind(this, i)}
               item={item.text}
               />
             ))}     
            </ul> 

            <p>{this.state.input}</p>
          </div>

        );
      }

    }


     ReactDOM.render(<App />, document.getElementById("root"));