2017-07-20 10 views
0

Ich bin sehr neu zu reagieren. Ich steckte beim Entfernen der Karte vom Bildschirm mit OnClick-Taste fest. Von diesem Punkt kann ich this.props.data bekommen und wenn ich console.log (this.props.data) zurückgeben michWie kann ich Requisiten in TaskList dynamisch manipulieren?

(2) [Object, Object] 
0: Object 
1: Object 

Deshalb möchte ich wissen, wie ich Objekt aus this.props.data entfernen können. Wenn ich splice Methode mit Index (der ist eigentlich eine ID des Objekts) auf diese Weise this.props.data.splice(index, 1) funktioniert es nicht korrekt, aber Element sind vom Bildschirm verschwinden. Diese Funktion löscht alles in der Reihenfolge von Anfang bis Ende. Bitte erklären Sie mir, wie ich die beste Lösung für diese Leistung bekommen kann.

hier ist der Code:

import React from "react"; 
import TaskList from './TaskList'; 
import update from 'immutability-helper'; 
import './../stylesheets/main.scss'; 

export default class Home extends React.Component { 
    constructor(props) { 
     super(props); 
     this.state = {}; 
     localStorage.getItem("tasks") ? (this.state.tasks = JSON.parse(localStorage.tasks)) : (this.state.tasks = []); 
    } 

    addTask(id) { 
     const newTasks = this.state.tasks; 
     let task = {type: 'do_it', id: '0', description: '', priority: '', time: new Date().toLocaleString()}; 
     let desc = document.getElementById("description").value; 
     let cardPriority = document.getElementById("priority-selector").value; 

     task.id = newTasks.length + 1; 
     task.description = desc; 
     task.priority = cardPriority; 
     newTasks.push(task); 
     localStorage.setItem('tasks', JSON.stringify(newTasks)); 
     this.setState({ 
      tasks: newTasks 
     }) 
    } 

    handleDrop(id, toType) { 
     const tasks = this.state.tasks; 
     const taskIndex = tasks.findIndex((task) => { 
      return task.id == id; 
     }); 
     const updatedTask = update(tasks[taskIndex], {type: {$set: toType}}); 
     const newTasks = update(tasks, { 
      $splice: [[taskIndex, 1, updatedTask]] 
     }); 
     localStorage.setItem('tasks', JSON.stringify(newTasks)); 
     this.setState({tasks: newTasks}); 
    } 

    render() { 
     return (
      <div className="page-home"> 
       <div className="input"> 
        <div className="inner"> 
         <h1>Kanban Board</h1> 
         <input name="description" type="text" id="description"/> 
         <select name="priority" id="priority-selector"> 
          <option value="">Priority:</option> 
          <option value="1">1: High</option> 
          <option value="2">2: Medium</option> 
          <option value="3">3: Low</option> 
         </select> <br/> 
         <button type="submit" className="submit" onClick={this.addTask.bind(this)}>Add task</button> 
        </div> 
       </div> 
       <div className="container"> 
        <div className="column"> 
         <h2>Do it</h2> 
         <TaskList 
          data={this.state.tasks} 
          type={'do_it'} 
         /> 
        </div> 
        <div className="column"> 
         <h2>In Progress</h2> 
         <TaskList 
          data={this.state.tasks} 
          type={'in_progress'} 
          allowedTypes={['do_it']} 
          handleDrop={this.handleDrop.bind(this)} 
         /> 
        </div> 
        <div className="column"> 
         <h2>Done</h2> 
         <TaskList 
          data={this.state.tasks} 
          type={'done'} 
          allowedTypes={['in_progress']} 
          handleDrop={this.handleDrop.bind(this)} 
         /> 
        </div> 
        <div className="column"> 
         <h2>Aborted</h2> 
         <TaskList 
          data={this.state.tasks} 
          type={'aborted'} 
          allowedTypes={['do_it', 'in_progress']} 
          handleDrop={this.handleDrop.bind(this)} 
         /> 
        </div> 
       </div> 
      </div> 
     ); 
    } 
} 

und hier ist Tasklist-Klasse:

import React from "react"; 
import { Draggable, Droppable } from 'react-drag-and-drop' 
import update from 'immutability-helper'; 

export default class TaskList extends React.Component { 

    static getElementId(e) { 
     let id = null; 
     for (let key in e) { 
      if (e[key] !== '') { 
       id = e[key]; 
      } 
     } 
     return id; 
    } 

    static sortByPriority(a, b) { 
     return b.priority - a.priority; 
    } 

    onDrop(e) { 
     if (!e) return; 
     const id = TaskList.getElementId(e); 
     this.props.handleDrop(id, this.props.type) 
    } 

    orderTasks() { 
     const tasks = this.props.data.filter((el) => { 
      return el.type === this.props.type; 
     }); 
     // tasks.sort(TaskList.sortByPriority); 

     tasks.sort(function (a, b) { 
      return new Date(a.date) - new Date(b.date); 
     }); 

     return tasks; 
    } 

    handleSubmit(e) { 
     e.preventDefault(); 
    } 

    editTask(e) { 

     //var desc = e.target.value; 
     // 
     //this.setState({ 
     // tasks: {description: desc} 
     //}) 

    } 

    deleteTask(index) { 

     var state = this.props.data; 

     console.log(index); 

     state.splice(index, 1); 

     localStorage.setItem('tasks', JSON.stringify(state)); 

     this.setState({ 
      tasks: state 
     }) 
    } 

    render() { 
     const tasks = this.orderTasks(); 

     return (
      <Droppable 
       className="list" types={this.props.allowedTypes} 
       onDrop={this.onDrop.bind(this)} 
      > 
       <ul> 
        {tasks.map((task) => { 

         return (
          <Draggable 
           type={this.props.type} 
           key={task.id} 
           data={task.id} 
          > 
           <li> 
            <div className="card"> 

             <b>Task description:</b><br/> 

             {task.type === 'do_it' ? 

              <form> 
               <input 
                type="text" 
                defaultValue={task.description} 
                onChange={this.editTask.bind(this)} 
               /> 
               <input 
                type="button" 
                onSubmit={this.handleSubmit.bind(this)} 
                value="Edit" 
               /> 
              </form> 

              : <p>{task.description}</p>} 

             <p><b>Time: </b>{task.time}</p> 

             <div className="priority"><b>Priority:</b> {task.priority}</div> 

             {task.type === 'aborted' ? <button className="close" 
                      onClick={this.deleteTask.bind(this, task.id)}>&times;</button> : null} 
             {task.type === 'done' ? <button className="close" 
                     onClick={this.deleteTask.bind(this, task.id)}>&times;</button> : null} 
            </div> 
           </li> 
          </Draggable> 
         ) 
        })} 
       </ul> 
      </Droppable> 
     ); 
    } 
} 

Antwort

1

Da Sie Arrays verwenden, können Sie etwas tun, eine Aufgabe Karte von DOM zu entfernen:

deleteTask: function(e) { 
    var index = this.props.items.indexOf(e.target.value); 
    this.props.items.splice(index, 1); 
    this.forceUpdate(); 
} 
+0

Ich hatte keine Ahnung, dass forceUpdate() existiert! Danke, dass du mir etwas Neues beigebracht hast. Aber es sieht so aus, als ob das React-Team von der Verwendung von forceUpdate() abrät. Es ist besser, den Zustand und die Requisiten in diesem Fall zu verwenden (ohne sie manuell zu mutieren). https://facebook.github.io/react/docs/react-component.html#forceupdate – hellojeffhall

+0

Ja in der Tat forceUpdate() ist veraltet und wird nicht in den zukünftigen Versionen von reagieren. Und ja, man sollte niemals Staat und Requisiten direkt mutieren. Ich habe dieses Beispiel zitiert, als Sie sagten "Ich bin sehr neu zu reagieren". Ich bin froh, dass ich dir etwas beibringen kann! –

+0

@ m-ketan Danke, aber irgendwie funktioniert diese Lösung nicht für meine App. – Spade

1

So wie Sie durch Zugabe zu Ihrem Staat eine Aufgabe hinzufügen, werden Sie Ihren Zustand ein aktualisieren müssen neue Aufgabengruppe, die die Aufgabe, die Sie löschen möchten, nicht enthält, und Reagieren wird dann die gelöschte Aufgabe aus dem DOM entfernen. In Ihrer deleteTask Funktion:

this.setState(state => ({ tasks : state.tasks.filter(x => x.id !== id) })) 

Nur eine Anmerkung: In der Regel wollen Sie direkt this.state mutiert zu vermeiden, wie Sie in addTasks tun, wenn Sie ein neues Element drücken. Stattdessen sollten Sie eine neue Array Erstellen die concat Funktion eines Array mit:

this.setState(state => ({ tasks: state.tasks.concat(task) })) 

oder die spread syntax von ES6 Verwendung:

this.setState(state => ({ tasks: [...state.tasks, task)] })) 

anzumerken, dass this.setState ein Objekt als Parameter annehmen kann, oder eine Funktion. Wenn eine Funktion ausgeführt wird, hat die Funktion den aktuellen Status als Parameter und wird als aktualisierter Status der Komponente definiert. Aus Gründen der Leistung aktualisiert React den Status manchmal nicht sofort. Wenn Sie einfach this.setState mit einem Objekt aufrufen, ist nicht garantiert, dass der gesamte Status aktuell ist.

+1

Nur ein zusätzlicher Hinweis: Wichtig in React ist, dass du nie etwas vom Rendern löschst. Sie aktualisieren den Status Ihrer App, und diese Änderung löst ein neues Rendering aus, bei dem die Ansicht aktualisiert wird, um den Status widerzuspiegeln. – hon2a

0

löste ich mein Ziel durch einfache for Schleife wie folgt aus:

deleteTask(id) { 

     const state = this.props.data; 

     for (var i = 0; i < state.length; i++) { 

      if (state[i].id === id) { 

       let current = state[i]; 

       state.splice(state.indexOf(current), 1); 
      } 
     } 

     localStorage.setItem('tasks', JSON.stringify(state)); 

     this.setState({ 
      tasks: state 
     }) 
    } 
Verwandte Themen