2017-10-23 4 views
0

これは私の最初の投稿です。 私はtodoアプリを作成中です。 プラスのボタンをクリックすると、私のアプリはタスクリストに新しいタスクを追加しています。少数のクリックでは簡単なタスクはほとんどありませんでしたが、問題は各タスクがアイコンを削除してしまいました。そのアイコンの属するアイコンが表示されます。ここで react.js少数のレンダリングされたコンポーネントのうちの1つを削除する

はApp.jsコード

class App extends React.Component { 
constructor(props){ 
    super(props); 
    this.handleDelete = this.handleDelete.bind(this); 
    this.addTask = this.addTask.bind(this); 
    this.state = {taskNum: 0, 
        delete: false    
    } 
} 
addTask(){ 
    this.setState({ 
     taskNum: this.state.taskNum +1, 
     delete:false 
    }); 
} 
handleDelete(e){ 
    console.log(e.target); 
    this.setState({delete: true}); 
} 
render() { 
    const tasks = []; 
    for (let i = 0; i < this.state.taskNum; i += 1) { 
     tasks.push(!this.state.delete && <Task key={i} number={i} deleteTask={this.handleDelete}/>); 
     }; 

    return (
    <div className="ui container content"> 
     <h2 className="centerHeader header">TODO LIST</h2> 
     <h3 className="taskheader secondaryHeader">Tasks <Icon className="addNew plus" action={this.addTask}/></h3> 
     <div className="ui container five column grid taskList"> 
      {tasks} 
     </div> ... 

であり、ここであるTask.js

export class Task extends React.Component { 
    constructor(props){ 
    super(props); 
    this.dataChanged = this.dataChanged.bind(this); 
    this.state ={message: 'TASK' + (this.props.number+1), 
       } 
    } 
    customValidateText(text) { 
     return (text.length > 0 && text.length < 31); 
    } 
    dataChanged(data) { 
     console.log(data.message); 
     this.setState({message: data.message}); 
    } 
    render(){ 
    const centerRow = classNames('textCenter', 'row'); 
    return (<div className="ui column task"> 
        <div className={centerRow}><InlineEdit 
       validate={this.customValidateText} 
       activeClassName="editing" 
       text={this.state.message} 
       paramName="message" 
       change={this.dataChanged} 
       style={{ 
       background: 'inherit', 
       textAlign:'center', 
       maxWidth: '100%' , 
       display: 'inline-block', 
       margin: 0, 
       padding: 0, 
       fontSize: '1em', 
       outline: 0, 
       border: 0 
       }} 
      /></div> 
        <div className={centerRow}><Icon className="browser outline huge center"/> </div> 
        <div className={centerRow}><Icon className="large maximize"/><Icon className="large save saveTask"/><Icon className="large trash outline" action={this.props.deleteTask} /></div> 
      </div> 
     ); 

私はe.targetとはparentNodeを選択しようと考えたが、私はthatsのかどうかわからないです適切な解決策を使用して以来、私はこの問題のための効率的な解決策を見つけることができますのでごみ箱のアイコンをクリックすると親コンポーネントだけが削除されます。

+0

を説明する行が意味するはずのApp状態で 'DELETE'は何ですか?コメントで私はあなたのコード内のいくつかの変更をしましたか特定のタスクを削除済みとしてマークするために、タスク状態にすることを意味しませんでしたか? – helb

+0

ええ、私が意味していること – Jake11

答えて

0

反応が強力である主な理由の一つは、それはあなたに多くのことをご例えばだから、自分でDOMに

を任意の操作を行うことなく、あなたのデータに基づいて、あなたのDOMを維持する能力を与えるということですあなたはいくつかの変更を行う必要があります。あなたの問題を解決する必要があります。

1-データの実際の状態を保持する必要があるため、ToDo項目を追加すると、コンポーネント表現。

2つのタスクを削除すると、データ自体が削除されるため、タスクの1つを削除すると、実際のデータが削除され、反応するとDOMの更新が処理されるため、コンポーネントが反応しないJSメソッド

3-どのように反応するのかを知る方法と、すべてのデータを処理する方法は、コンポーネントstateによって管理されます。したがって、コンポーネントstateにデータを保存し、 stateを更新すると反応し、再び表示する必要があることがわかりますが、新しい更新されたタスクリストが表示されます



なぜ

class App extends React.Component { 
    constructor(props){ 
     super(props); 
     this.handleDelete = this.handleDelete.bind(this); 
     this.addTask = this.addTask.bind(this); 
     this.state = { 
       tasks: [ ], // this is the array that will hold the actual data and based on its content react will handle rendering the correct data 
       counter : 1 // this counter is incremented every task addition just to make sure we are adding different task name just for the example explanation 
      } 
     } 
    } 

    addTask(){ 
     this.setState({ 
      tasks: this.state.tasks.push("TASK" + counter); //This how we add a new task as i said you are adding an actual task data to the state 
      counter : this.state.counter + 1 //increment counter to have different task name for the next addition 
     }); 
    } 

    //i changed this function to accept the task name so when you click delete it will call this function with task name as parameter 
    //then we use this task name to actually remove it from the tasks list data in our state 
    handleDelete(taskToDelete){ 

     this.setState({ 
      //the filter function below will remove the task from the array in our state 
      //After this state update, react will render the component again but now with the tasks list after removing deleting this one 
      tasks : this.state.tasks.filter((task) => { 
       if(task != taskToDelete) 
        return word; 
      }) 
     }); 
    } 

    render() { 
     const tasks = []; 
     //Notice here we pass an actual data to every Task component so i am adding prop message to take the value from this.state.tasks[index] 
     for (let i=0 ; i< this.state.tasks.length ; i++) 
     { 
      tasks.push(<Task key={i} message={this.state.tasks[i]} deleteTask={this.handleDelete}/>); 
     } 


     return (
     <div className="ui container content"> 
      <h2 className="centerHeader header">TODO LIST</h2> 
      <h3 className="taskheader secondaryHeader">Tasks <Icon className="addNew plus" action={this.addTask}/></h3> 
      <div className="ui container five column grid taskList"> 
       {tasks} 
      </div> ... 
      ) 
    } 
} 

タスクコンポーネント

export class Task extends React.Component { 
    constructor(props){ 
     super(props); 
     this.dataChanged = this.dataChanged.bind(this); 
     this.removeCurrentTask = this.removeCurrentTask.bind(this); 
     //Here i am setting the state from the passed prop message 
     this.state ={ 
      message: this.props.message 
     } 
    } 

    customValidateText(text) { 
     return (text.length > 0 && text.length < 31); 
    } 

    dataChanged(data) { 
     console.log(data.message); 
     this.setState({message: data.message}); 
    } 

    removeCurrentTask(){ 
     //calling the deleteTask function with the current task name. 
     this.props.deleteTask(this.state.message); 
    } 

    render(){ 
     const centerRow = classNames('textCenter', 'row'); 
     return (
      <div className="ui column task"> 
       <div className={centerRow}><InlineEdit 
         validate={this.customValidateText} 
         activeClassName="editing" 
         text={this.state.message} 
         paramName="message" 
         change={this.dataChanged} 
         style={{ 
         background: 'inherit', 
         textAlign:'center', 
         maxWidth: '100%' , 
         display: 'inline-block', 
         margin: 0, 
         padding: 0, 
         fontSize: '1em', 
         outline: 0, 
         border: 0 
         }} 
        /></div> 
       <div className={centerRow}><Icon className="browser outline huge center"/> </div> 
       //Notice the action handler here is changed to use removeCurrentTask defined in current component 
       //BTW i don't know how Icon is handling the action property ... but now you can simply use onClick and call removeCurrentTask 
       <div className={centerRow}><Icon className="large maximize"/><Icon className="large save saveTask"/><Icon className="large trash outline" action={this.removeCurrentTask} /></div> 
      </div> 
      ); 
    } 
} 
+0

あなたは歓迎されています...私はまた、コメントラインを使ってあなたのコードで行われなければならないすべての変更を含む答えを編集しました。それ以上 –

+0

今すぐあなたは私がそれをすぐに実装しようとする多くの助け:) – Jake11